/**
 @file ctc_asw_acl.c

 @author  Copyright (C) 2020 Centec Networks Inc.  All rights reserved.

 @date 2020-06-15

 @version v2.0
*/

/****************************************************************************
*
* Header Files
*
****************************************************************************/
#include "ctc_asw_common.h"
#include "ctc_parser.h"
#include "ctc_register.h"
#include "ctc_asw_acl.h"
#include "asw/include/drv_api.h"
/****************************************************************************
*
* Defines and Macros
*
*****************************************************************************/
#define key_valid_field 0
#define key_type_field  1
#define  CTC_ASW_ACL_RANGE_NUM   12
#define  CTC_ASW_ACL_UDF_BYTE_NUM            16           /**< [TMA] Acl udf byte number */
#define  CTC_ASW_ACL_UDF_ENTRY_NUM           8            /**< [TMA] Acl udf entry number */
#define  CTC_ASW_ACL_UDF_FIELD_NUM           4            /**< [TMA] number of ACL udf field */
#define  CTC_ASW_ACL_ENTRY_NUM              128

#define SYS_ACL_UDF_PRI_2_IDX(prio)     (CTC_ASW_ACL_UDF_BYTE_NUM - 1 - prio)
#define ACL_ENTRY_ID_CHECK(id)\
    {\
        CTC_MAX_VALUE_CHECK(id, CTC_ASW_ACL_ENTRY_NUM - 1);\
    }

#define ACL_UDF_ID_CHECK(id)\
        {\
            CTC_MAX_VALUE_CHECK(id, CTC_ASW_ACL_UDF_ENTRY_NUM - 1);\
        }

#define CTC_ASW_SET_HW_UDF(dest, src)     \
    { \
        (dest)[3] = ((src)[12] << 24 | src[13]<<16| src[14]<<8|src[15]);                    \
        (dest)[2] = ((src)[8] << 24 | src[9]<<16| src[10]<<8|src[11]);                       \
        (dest)[1] = ((src)[4] << 24 | src[5]<<16| src[6]<<8|src[7]);                        \
        (dest)[0] = ((src)[0] << 24 | src[1]<<16| src[2]<<8|src[3]);                        \
    }

#define ACL_SET_HW_MAC(d, s)    CTC_ASW_SET_HW_MAC(d, s)
/****************************************************************************
*
* Global and Declaration
*
*****************************************************************************/
typedef struct
{
    ds_t key;
    ds_t mask;
    ds_t action;
}sys_acl_buffer_t;

struct sys_acl_entry_s
{
    uint8 key_type;
    uint32 entry_id;
    sys_acl_buffer_t buffer;
};
typedef struct sys_acl_entry_s sys_acl_entry_t;

struct sys_acl_udf_entry_s
{
    uint8 udf_id;
    sys_acl_buffer_t buffer;
};
typedef struct sys_acl_udf_entry_s sys_acl_udf_entry_t;

struct drv_acl_port_info_s
{
    uint16 gport;
    uint16 gport_mask;

    uint8  gport_type;
    uint8  gport_type_mask;

    uint8  bitmap;
    uint8  bitmap_mask;
};
typedef struct drv_acl_port_info_s  drv_acl_port_info_t;

typedef int32 (* SYS_CB_ACL_BUILD_KEY_FUNC_T)(uint8 lchip, ctc_field_key_t* pKey, sys_acl_entry_t* pe,uint8 is_add);

uint8 g_acl_key_size[CTC_ACL_KEY_NUM] = {0};
uint32 g_acl_key_tbl[CTC_ACL_KEY_NUM] = {0};

uint8 g_acl_hw_key_type[] = {CTC_ACL_KEY_MAC, CTC_ACL_KEY_MAC_EXT, CTC_ACL_KEY_IPV4, CTC_ACL_KEY_MAC_IPV4,
                              CTC_ACL_KEY_IPV4_EXT,CTC_ACL_KEY_MAC_IPV6, CTC_ACL_KEY_IPV6, CTC_ACL_KEY_IPV6_EXT,
                              CTC_ACL_KEY_UDF};
SYS_CB_ACL_BUILD_KEY_FUNC_T g_acl_build_key_func_cb[CTC_ACL_KEY_NUM] = {0};
/****************************************************************************
*
*  Functions
*
*****************************************************************************/
extern int32
_ctc_asw_register_get_glb_acl_property(uint8 lchip, ctc_global_acl_property_t* p_acl_prop);

extern int32
_ctc_asw_qos_get_cpu_reason_queue(uint8 lchip, uint16 cpu_reason, uint8* p_queue_id);

/*check if hw index exist any key*/
STATIC uint32
_ctc_asw_acl_check_key_index(uint8 lchip, ctc_acl_entry_t* acl_entry, void * ds_key)
{
    uint32 cmd = 0;
    uint32 key_tbl = 0;
    uint8 key_valid = 0;
    uint8 key_type = 0;
    uint8 ksize = g_acl_key_size[acl_entry->key_type];
    uint32 index_tmp = 0;
    ds_t tmp_key = {0};
    ds_t tmp_mask = {0};
    uint8 i = 0;
    uint8 times = 0;
    mask_tbl_entry_t tcam_entry;
    tcam_entry.data_entry = tmp_key;
    tcam_entry.mask_entry = tmp_mask;

    key_tbl = g_acl_key_tbl[acl_entry->key_type];
    key_valid = DRV_GET_FIELD_V(lchip, key_tbl, key_valid_field, ds_key);
    if(key_valid)
    {
        return CTC_E_INVALID_PARAM;
    }

    index_tmp = (acl_entry->entry_id >> 2) << 2;
    cmd = DRV_IOR(Key640Macipv6udfView0_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, index_tmp, cmd, &tcam_entry));
    if(0x01 == GetKey640Macipv6udfView0(V, valid_f, tmp_key))
    {
        key_type = GetKey640Macipv6udfView0(V, keyType_f, tmp_key);
        key_type = g_acl_hw_key_type[key_type];
        if(g_acl_key_size[key_type] == 4)
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    index_tmp = (ksize==4 ? ((acl_entry->entry_id >> 2) << 2) : acl_entry->entry_id);
    times = (ksize==2?0:(ksize==4? 2 : 1));
    for(i = 0; i < times ; i++, index_tmp+=2)
    {
        cmd = DRV_IOR(Key320MacipudfView0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, index_tmp, cmd, &tcam_entry));
        if(GetKey320MacipudfView0(V, valid_f, tmp_key) == 0x01)
        {
            key_type = GetKey320MacipudfView0(V, keyType_f, tmp_key);
            key_type = g_acl_hw_key_type[key_type];
            if(g_acl_key_size[key_type] == 2)
            {
                return CTC_E_INVALID_PARAM;
            }
        }
    }

    index_tmp = (ksize==4 ? ((acl_entry->entry_id >> 2) << 2) : acl_entry->entry_id);
    times = (ksize==1?0:(ksize==4? 4 : 2));
    for(i = 0; i < times ; i++,index_tmp++)
    {
        cmd = DRV_IOR(Key160MacView0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, index_tmp, cmd, &tcam_entry));

        if(GetKey160MacView0(V, valid_f, tmp_key) == 0x01)
        {
            key_type = GetKey160MacView0(V, keyType_f, tmp_key);
            key_type = g_acl_hw_key_type[key_type];
            if(g_acl_key_size[key_type] == 1)
            {
                return CTC_E_INVALID_PARAM;
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_get_key_type(uint8 lchip, uint32 entry_id, uint8* o_key_type, uint8 valid)
{
     uint8 key_size = 0;
     uint8 key_type = 0;
     uint8 key_valid = 0;
     ds_t tmp_key = {0};
     ds_t tmp_mask = {0};
     uint32 cmd = 0;
     uint8 valid_check = 0;
     mask_tbl_entry_t tcam_entry;
     tcam_entry.data_entry = (uint32 *)&tmp_key;
     tcam_entry.mask_entry = (uint32 *)&tmp_mask;

     if((entry_id & 0x03) == 0)
     {
        cmd = DRV_IOR(Key640Macipv6udfView0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, entry_id, cmd, &tcam_entry));

        key_type = GetKey640Macipv6udfView0(V, keyType_f, tmp_key);
        key_type = g_acl_hw_key_type[key_type];
        if(GetKey640Macipv6udfView0(V, keyType_f, tmp_mask) == 0xf)
        {
            key_valid = GetKey640Macipv6udfView0(V, valid_f, tmp_key);
    
            key_size = g_acl_key_size[key_type];
            valid_check = valid ? 0x01 : 0;

            if( (key_size == 4 && key_valid == valid_check))
            {
                *o_key_type = key_type;
                return CTC_E_NONE;
            }
        }
     }
     if((entry_id & 0x01) == 0)      /*entry_id % 2 == 0*/
     {
        cmd = DRV_IOR(Key320MacipudfView0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, entry_id, cmd, &tcam_entry));

        key_type = GetKey320MacipudfView0(V, keyType_f, tmp_key);
        key_type = g_acl_hw_key_type[key_type];
        if(GetKey320MacipudfView0(V, keyType_f, tmp_mask) == 0xf)
        {
            key_valid = GetKey320MacipudfView0(V, valid_f, tmp_key);
            key_size = g_acl_key_size[key_type];
            valid_check = valid ? 0x01 : 0;

            if(key_size == 2 && key_valid == valid_check)
            {
                *o_key_type = key_type;
                return CTC_E_NONE;
            }
        }
     }

     {
        cmd = DRV_IOR(Key160MacView0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, entry_id, cmd, &tcam_entry));

        key_type = GetKey160MacView0(V, keyType_f, tmp_key);
        key_type = g_acl_hw_key_type[key_type];
        if(GetKey160MacView0(V, keyType_f, tmp_mask) == 0xf)
        {
            key_valid = GetKey160MacView0(V, valid_f, tmp_key);
            key_size = g_acl_key_size[key_type];

            if( (key_size == 1 && key_valid == (valid ? 0x01 : 0)))
            {
                *o_key_type = key_type;
                return CTC_E_NONE;
            }
        }
     }
     return CTC_E_INVALID_CONFIG;
}


int32
_ctc_asw_acl_add_remove_valid(uint8 lchip, uint32 entry_id, uint8 is_add)
{
    uint32 cmd = 0;
    uint8 key_type = 0;
    uint32 key_tbl = 0;
    ds_t key_data = {0};
    ds_t key_mask = {0};
    mask_tbl_entry_t tcam_key;
    tcam_key.data_entry = key_data;
    tcam_key.mask_entry = key_mask;

    CTC_ERROR_RETURN(_ctc_asw_acl_get_key_type(lchip, entry_id, &key_type, !is_add));
    key_tbl = g_acl_key_tbl[key_type];

    cmd = DRV_IOR(key_tbl, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, entry_id, cmd, &tcam_key));

    DRV_SET_FIELD_V(lchip, key_tbl, key_valid_field, key_data, (is_add ? 1 : 0));

    cmd = DRV_IOW(key_tbl, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, entry_id, cmd, &tcam_key));

    return CTC_E_NONE;
}

STATIC int32
__ctc_asw_acl_add_basic_field(uint8 lchip, ctc_acl_field_action_t* action_field, AclBaseAction_m* paction, AclQosAction_m* p_qos_action, uint8 is_add)
{
	ctc_acl_vlan_edit_t* p_vlan_edit = NULL;
    ctc_acl_table_map_t* p_qos_map = NULL;
    ctc_acl_to_cpu_t * p_cpu = NULL;
    uint8 loopback_en = 0;
    uint8 drop_en = 0;
    uint32 value = 0;
    switch(action_field->type)
    {
        case CTC_ACL_FIELD_ACTION_DISCARD:
            SetAclBaseAction(V, drop_f, paction, is_add ? 1:0);
            loopback_en = GetAclBaseAction(V, loopbackEnable_f,paction);
            if (loopback_en)
            {
                SetAclBaseAction(V, loopbackIndex_f, paction, is_add ? 1:0);
            }
            break;
        case CTC_ACL_FIELD_ACTION_RANDOM_LOG:
            SetAclBaseAction(V, mirrorEn_f, paction, is_add ? 1:0);
            break;
        case CTC_ACL_FIELD_ACTION_DENY_LEARNING:
            SetAclBaseAction(V, bypassLearning_f, paction, is_add ? 1:0);
            break;
        case CTC_ACL_FIELD_ACTION_CP_TO_CPU:
            {
                uint8 queue_id = 0;
                CTC_PTR_VALID_CHECK(action_field->ext_data);
                p_cpu = (ctc_acl_to_cpu_t*)(action_field->ext_data);

                CTC_MAX_VALUE_CHECK(p_cpu->mode, CTC_ACL_TO_CPU_MODE_TO_CPU_COVER);
                
                if (p_cpu->mode == CTC_ACL_TO_CPU_MODE_TO_CPU_COVER)
                {
                    SetAclBaseAction(V, copyToCpu_f, paction, is_add ? 1:0);
                    if (is_add)
                    {
                        CTC_ERROR_RETURN(_ctc_asw_qos_get_cpu_reason_queue(lchip, p_cpu->cpu_reason_id, &queue_id));
                        SetAclQosAction(V, qp2cpu_f, p_qos_action, queue_id);
                    }
                    SetAclQosAction(V, changeQp2cpu_f, p_qos_action, is_add ? 1:0);
                }
                else
                {
                    SetAclBaseAction(V, copyToCpu_f, paction, is_add ? 1:0);
                    SetAclQosAction(V, changeQp2cpu_f, p_qos_action, 0);
                }
                break;
            }
            break;
        case CTC_ACL_FIELD_ACTION_REDIRECT_PORT:
            if (action_field->data1 & 0x1F)
            {
                SetAclBaseAction(V, redirectLagBitmap_f, paction, is_add ? (action_field->data1&0x1F):0);
                SetAclBaseAction(V, bitmapMode_f, paction, is_add ? 1:0);
            }
            else
            {
                SetAclBaseAction(V, redirectLagBitmap_f, paction, 0);
                SetAclBaseAction(V, bitmapMode_f, paction, 0);
            }
            SetAclBaseAction(V, redirectPortBitmap_f, paction, is_add ? (action_field->data0 & 0x1FFFFFFF) : 0);
            SetAclBaseAction(V, redirectEnable_f, paction, is_add ? 1:0);
            break;
        case CTC_ACL_FIELD_ACTION_SWAP_MAC:
            SetAclBaseAction(V, loopbackEnable_f,paction, is_add ? 1:0);
            drop_en = GetAclBaseAction(V, drop_f,paction);
            SetAclBaseAction(V, loopbackIndex_f, paction, drop_en ? 1:0);
            break;
        case CTC_ACL_FIELD_ACTION_STATS:
            CTC_MAX_VALUE_CHECK(action_field->data0, CTC_ASW_MAX_STATS_ID);
            SetAclQosAction(V, counterIndex_f, p_qos_action, action_field->data0);
            SetAclQosAction(V, counterEnable_f, p_qos_action, is_add ? 1 : 0);
            break;
        case CTC_ACL_FIELD_ACTION_DSCP:
            CTC_MAX_VALUE_CHECK(action_field->data0, 0x3F);
            SetAclQosAction(V, remarkDscp_f, p_qos_action, action_field->data0);
            SetAclQosAction(V, remarkDscpMode_f, p_qos_action, is_add ? 1 : 0);
            break;
        case CTC_ACL_FIELD_ACTION_MICRO_FLOW_POLICER:
            CTC_MAX_VALUE_CHECK(action_field->data0, 0x3F);
            SetAclQosAction(V, policeIndex_f, p_qos_action, action_field->data0);
            SetAclQosAction(V, policeMode_f, p_qos_action, is_add ? 1 : 0);
            SetAclQosAction(V, counterIndex_f, p_qos_action, action_field->data0+CTC_ASW_MAX_STATS_ID+1);
            SetAclQosAction(V, counterEnable_f, p_qos_action, is_add ? 1 : 0);
            break;
        case CTC_ACL_FIELD_ACTION_QOS_TABLE_MAP:
        {
            uint8 domain = 0;
            CTC_PTR_VALID_CHECK(action_field->ext_data);
            p_qos_map = (ctc_acl_table_map_t*)(action_field->ext_data);

            domain= p_qos_map->table_map_id;
            CTC_MAX_VALUE_CHECK(domain, 7);
            CTC_MAX_VALUE_CHECK(p_qos_map->table_map_type, 1);
            
            domain = p_qos_map->table_map_type ? (domain | 0x8) : domain;
            SetAclQosAction(V, priIndex_f, p_qos_action, domain);
            SetAclQosAction(V, trustPriMode_f, p_qos_action, p_qos_map->table_map_type ? 3 : 2);
            break;
        }
        case CTC_ACL_FIELD_ACTION_VLAN_EDIT:
            CTC_PTR_VALID_CHECK(action_field->ext_data);
            p_vlan_edit = (ctc_acl_vlan_edit_t*)(action_field->ext_data);
            CTC_MAX_VALUE_CHECK(p_vlan_edit->scos_sl, CTC_ACL_VLAN_TAG_SL_MAX);
            CTC_MAX_VALUE_CHECK(p_vlan_edit->scos_new, 7);
            CTC_MAX_VALUE_CHECK(p_vlan_edit->scfi_new, 1);
            switch(p_vlan_edit->scos_sl)
            {
            case CTC_ACL_VLAN_TAG_SL_ALTERNATIVE:
                SetAclQosAction(V, remarkScosMode_f, p_qos_action, is_add ? 2 : 0);
                break;
            case CTC_ACL_VLAN_TAG_SL_NEW:
                SetAclQosAction(V, remarkScosMode_f, p_qos_action, is_add ? 1 : 0);
                value = ((p_vlan_edit->scos_new << 1) | (p_vlan_edit->scfi_new));
                SetAclQosAction(V, remarkScos_f, p_qos_action, is_add ? value : 0);
                break;
            default:
                SetAclQosAction(V, remarkScosMode_f, p_qos_action, 0);
                break;
            }
            break;
        default:
        	return CTC_E_NOT_SUPPORT;
    }
    return CTC_E_NONE;
}

int32
_ctc_asw_acl_build_action_field_list(uint8 lchip, uint32 entry_id, ctc_acl_field_action_t* p_field_list, uint32* p_field_cnt, uint8 is_add)
{
    int32 ret = CTC_E_NONE;
    uint32  field_id      = 0;
    uint32 cmd = 0;
    uint32 field_cnt = *p_field_cnt;
    AclBaseAction_m action;
    AclQosAction_m qos_action;
    ctc_acl_field_action_t*   p_field       = NULL;

    cmd = DRV_IOR(AclBaseAction_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, entry_id, cmd, &action);

    cmd = DRV_IOR(AclQosAction_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, entry_id, cmd, &qos_action);

    for (field_id=0; field_id<field_cnt; field_id+=1)
    {
        p_field = p_field_list + field_id;

        ret = __ctc_asw_acl_add_basic_field(lchip, p_field, &action, &qos_action, is_add);
    }

    cmd = DRV_IOW(AclBaseAction_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, entry_id, cmd, &action);

    cmd = DRV_IOW(AclQosAction_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, entry_id, cmd, &qos_action);

    return ret;
}

STATIC int32
_ctc_asw_acl_map_l3_type(uint32 type, uint32* tmp_data)
{
    switch(type)
    {
        case CTC_PARSER_L3_TYPE_NONE:
            *tmp_data = 0;
            break;
        case CTC_PARSER_L3_TYPE_IPV4:
            *tmp_data = 1;
            break;
        case CTC_PARSER_L3_TYPE_IPV6:
            *tmp_data = 2;
            break;
        default :
            return CTC_E_INVALID_PARAM;
    }
    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_map_l4_type(uint32 type, uint32* tmp_data)
{
    switch(type)
    {
        case CTC_PARSER_L4_TYPE_NONE:
            *tmp_data = 0;
            break;
        case CTC_PARSER_L4_TYPE_TCP:
            *tmp_data = 2;
            break;
        case CTC_PARSER_L4_TYPE_UDP:
            *tmp_data = 1;
            break;
        case CTC_PARSER_L4_TYPE_ICMP:
            *tmp_data = 4;
            break;
        case CTC_PARSER_L4_TYPE_IGMP:
            *tmp_data = 5;
            break;
        default :
            return CTC_E_INVALID_PARAM;
    }
    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_map_ip_frag(uint8 ctc_ip_frag, uint32* o_frag_info, uint32* o_frag_info_mask)
{
    uint32 frag_info = 0;
    uint32 frag_info_mask = 0;
    switch (ctc_ip_frag)
    {
    case CTC_IP_FRAG_NON:
        /* Non fragmented */
        frag_info      = 0;
        frag_info_mask = 3;
        break;

    case CTC_IP_FRAG_FIRST:
        /* Fragmented, and first fragment */
        frag_info      = 2;
        frag_info_mask = 3;
        break;

    case CTC_IP_FRAG_NON_OR_FIRST:
        /* Non fragmented OR Fragmented and first fragment */
        frag_info      = 0;
        frag_info_mask = 1;     /* mask frag_info as 0x */
        break;

    case CTC_IP_FRAG_NOT_FIRST:
        /* Not first fragment (Fragmented of cause) */
        frag_info      = 3;
        frag_info_mask = 3;
        break;

    case CTC_IP_FRAG_YES:
        /* Any Fragmented */
        frag_info      = 2;
        frag_info_mask = 2;
        break;

    default:
        return CTC_E_INVALID_PARAM;
    }

    *o_frag_info = frag_info;
    *o_frag_info_mask = frag_info_mask;
    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_build_port_info(uint8 lchip,   ctc_field_key_t* key_field, drv_acl_port_info_t* pport_drv)
{
    uint16 bitmap_12    = 0;
    uint8  bitmap_base =0;
    uint16 bitmap_12_mask    = 0;
    ctc_field_port_t* p_field_port = (ctc_field_port_t*)key_field->ext_data;

    CTC_PTR_VALID_CHECK(key_field->ext_data);

    switch(p_field_port->type)
    {
    case CTC_FIELD_PORT_TYPE_PORT_BITMAP:
        /* have been checked */
        for(bitmap_base = 0; bitmap_base < 3; bitmap_base++)
        {
            bitmap_12 = (p_field_port->port_bitmap[0] >> (bitmap_base*12))&0xFFF;
            if(bitmap_12)
            {
                break;
            }
        }
        bitmap_12_mask = (~bitmap_12)&0xFFF;

        pport_drv->gport = (bitmap_base << 12)|bitmap_12;
        pport_drv->gport_mask = (0x03 << 12)|bitmap_12_mask;

        pport_drv->gport_type      = 0;
        pport_drv->gport_type_mask = 3;
        break;
    /*case CTC_FIELD_PORT_TYPE_LOGIC_PORT:
        pport_drv->gport = p_field_port->logic_port;
        pport_drv->gport_mask = ((ctc_field_port_t*)key_field->ext_mask)->logic_port;

        pport_drv->gport_type      = 1;
        pport_drv->gport_type_mask = 3;
        break;*/

    default:
        return CTC_E_INVALID_PARAM;
    }
    return CTC_E_NONE;
}


STATIC int32
_ctc_asw_acl_add_udf_entry_key_field(uint8 lchip, mask_tbl_entry_t* udf_entry, ctc_field_key_t* key_field, uint8 is_add)
{
    uint32 tmp_data = 0;
    uint32 tmp_mask = 0;
    drv_acl_port_info_t port_drv;
    UdfCam_m* udf_cam = NULL;
    UdfCam_m* udf_cam_mask = NULL;

    udf_cam = (UdfCam_m*)udf_entry->data_entry;
    udf_cam_mask = (UdfCam_m*)udf_entry->mask_entry;

    switch(key_field->type)
    {
        case CTC_FIELD_KEY_PORT:
            {
                _ctc_asw_acl_build_port_info(lchip, key_field, &port_drv);
                
                SetUdfCam(V, sportBitmap_f, udf_cam, port_drv.gport);
                SetUdfCam(V, sportBitmap_f, udf_cam_mask, port_drv.gport_mask);
                SetUdfCam(V, portType_f, udf_cam, port_drv.gport_type);
                SetUdfCam(V, portType_f, udf_cam_mask, port_drv.gport_type_mask);
            }
            break;

        case CTC_FIELD_KEY_ETHER_TYPE:
            SetUdfCam(V, ethtype_f, udf_cam, key_field->data);
            SetUdfCam(V, ethtype_f, udf_cam_mask, key_field->mask);
            break;

        case CTC_FIELD_KEY_IP_OPTIONS:
            SetUdfCam(V, ipOption_f, udf_cam, key_field->data);
            SetUdfCam(V, ipOption_f, udf_cam_mask, key_field->mask);
            break;

        case CTC_FIELD_KEY_IP_FRAG:
            CTC_ERROR_RETURN(_ctc_asw_acl_map_ip_frag(key_field->data, &tmp_data, &tmp_mask));
            SetUdfCam(V, fragmentFlag_f, udf_cam, tmp_data);
            SetUdfCam(V, fragmentFlag_f, udf_cam_mask, tmp_mask);
            break;

        case CTC_FIELD_KEY_L4_TYPE:
            CTC_ERROR_RETURN(_ctc_asw_acl_map_l4_type(key_field->data, &tmp_data));
            SetUdfCam(V, l4Type_f, udf_cam, tmp_data);
            SetUdfCam(V, l4Type_f, udf_cam_mask, key_field->mask);
            break;

        case CTC_FIELD_KEY_L2_TYPE:
            SetUdfCam(V, l2Type_f, udf_cam, key_field->data);
            SetUdfCam(V, l2Type_f, udf_cam_mask, key_field->mask);
            break;

        case CTC_FIELD_KEY_L4_DST_PORT:
            SetUdfCam(V, l4Dport_f, udf_cam, key_field->data);
            SetUdfCam(V, l4Dport_f, udf_cam_mask, key_field->mask);
            break;

        case CTC_FIELD_KEY_L4_SRC_PORT:
            SetUdfCam(V, l4Sport_f, udf_cam, key_field->data);
            SetUdfCam(V, l4Sport_f, udf_cam_mask, key_field->mask);
            break;

        case CTC_FIELD_KEY_STAG_VALID:
        case CTC_FIELD_KEY_CTAG_VALID:
            tmp_data = GetUdfCam(V, l2TagStatus_f, udf_cam);
            tmp_mask = GetUdfCam(V, l2TagStatus_f, udf_cam_mask);
            if(key_field->type == CTC_FIELD_KEY_STAG_VALID)
            {
                tmp_data = (tmp_data & 0x02) | (key_field->data);
                tmp_mask = (tmp_mask & 0x02) | (key_field->mask);
            }
            else
            {
                tmp_data = (tmp_data & 0x01) | (key_field->data << 1);
                tmp_mask = (tmp_mask & 0x01) | (key_field->mask << 1);
            }
            SetUdfCam(V, l2TagStatus_f, udf_cam, tmp_data);
            SetUdfCam(V, l2TagStatus_f, udf_cam_mask, tmp_mask);
            break;

        case CTC_FIELD_KEY_IP_PROTOCOL:
            SetUdfCam(V, ipProtocol_f, udf_cam, key_field->data);
            SetUdfCam(V, ipProtocol_f, udf_cam_mask, key_field->mask);
            break;
        case CTC_FIELD_KEY_UDF_ENTRY_VALID:
            SetUdfCam(V, valid_f, udf_cam, (is_add)?1:0);
            SetUdfCam(V, valid_f, udf_cam_mask, key_field->mask & 0x1);
            break;
        default:
            return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_check_port_info(    ctc_field_key_t* p_field)
{
    ctc_field_port_t *p_ctc_field_port;
    uint8 loop = 0;
    uint8 count = 0;
    
    CTC_PTR_VALID_CHECK(p_field->ext_data);
    p_ctc_field_port = (ctc_field_port_t*)(p_field->ext_data);
    /*if(CTC_FIELD_PORT_TYPE_LOGIC_PORT == p_ctc_field_port->type)
    {
        CTC_MAX_VALUE_CHECK(p_ctc_field_port->logic_port,  0x3f);
        CTC_PTR_VALID_CHECK(p_field->ext_mask);
    }
    else*/ if (CTC_FIELD_PORT_TYPE_PORT_BITMAP != p_ctc_field_port->type)
    {
        CTC_ERROR_RETURN(CTC_E_INVALID_PARAM);
    }
    if(p_ctc_field_port->port_bitmap[0] >> CTC_ASW_MAX_PORT_NUM_PER_CHIP)
    {
        CTC_ERROR_RETURN(CTC_E_INVALID_PARAM);
    }
    for(loop = 0; loop < 3; loop++)
    {
        if( (p_ctc_field_port->port_bitmap[0] >> (loop*12))&0xFFF )
        {
            count++;
        }
    }
    if(count != 1)
    {
        return CTC_E_INVALID_CONFIG;
    }

    return CTC_E_NONE;
}


STATIC int32
_ctc_asw_acl_check_udf_entry_key_field(uint8 lchip,  ctc_field_key_t* key_field)
{
    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        {
            CTC_ERROR_RETURN(_ctc_asw_acl_check_port_info(key_field));
        }
        break;
    case CTC_FIELD_KEY_IP_OPTIONS:
        CTC_MAX_VALUE_CHECK(key_field->data, 1);
        break;
    case CTC_FIELD_KEY_IP_FRAG:
        CTC_MAX_VALUE_CHECK(key_field->data, CTC_IP_FRAG_MAX - 1);
        break;
    case CTC_FIELD_KEY_L4_TYPE:
        CTC_MAX_VALUE_CHECK(key_field->data, MAX_CTC_PARSER_L4_TYPE - 1);
        break;
    case CTC_FIELD_KEY_L4_DST_PORT:
    case CTC_FIELD_KEY_L4_SRC_PORT:
        CTC_MAX_VALUE_CHECK(key_field->data, 0xFFFF);
        break;
    case CTC_FIELD_KEY_IP_PROTOCOL:
        CTC_MAX_VALUE_CHECK(key_field->data, 0xFF);
        break;
    case CTC_FIELD_KEY_L2_TYPE:
         CTC_MAX_VALUE_CHECK(key_field->data, CTC_PARSER_L2_TYPE_ETH_SNAP );
      break;
    default:
        return CTC_E_NONE;
    }

    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_check_key_field(uint8 key_type, ctc_field_key_t* p_field_list, uint32 field_cnt)
{
    uint32  field_id      = 0;
    ctc_field_key_t* p_field = NULL;
    uint32 kset[CTC_B2W_SIZE(CTC_FIELD_KEY_NUM)] = {0};
    uint32 l3_type = 0;
    uint8 use_range_bmp = 0;

    for (field_id=0; field_id<field_cnt; field_id+=1)
    {
        p_field = p_field_list + field_id;
        CTC_PTR_VALID_CHECK(p_field);
        if(p_field->type > CTC_FIELD_KEY_NUM -1)
        {
            return CTC_E_NOT_SUPPORT;
        }
        CTC_BMP_SET(kset, p_field->type);

        if(p_field->type == CTC_FIELD_KEY_L3_TYPE)
        {
            l3_type = p_field->data;
        }
    }
    for (field_id=0; field_id<field_cnt; field_id+=1)
    {
        p_field = p_field_list + field_id;
        switch(p_field->type)
        {
            case CTC_FIELD_KEY_PORT:
                {
                    CTC_ERROR_RETURN(_ctc_asw_acl_check_port_info(p_field));
                }
                break;
            case CTC_FIELD_KEY_ETHER_TYPE:
                CTC_MAX_VALUE_CHECK(p_field->data, 0xffff);
                break;
            case CTC_FIELD_KEY_MAC_SA:
            case CTC_FIELD_KEY_MAC_DA:
                 CTC_PTR_VALID_CHECK(p_field->ext_data);
                break;
            case CTC_FIELD_KEY_STAG_VALID:
            case CTC_FIELD_KEY_CTAG_VALID:
                break;
            case CTC_FIELD_KEY_STAG_CFI:
            case CTC_FIELD_KEY_CTAG_CFI:
                CTC_MAX_VALUE_CHECK(p_field->data, 1);
                break;
            case CTC_FIELD_KEY_STAG_COS:
            case CTC_FIELD_KEY_CTAG_COS:
                CTC_MAX_VALUE_CHECK(p_field->data, 7);
                break;
            case CTC_FIELD_KEY_SVLAN_ID:
            case CTC_FIELD_KEY_CVLAN_ID:
                CTC_MAX_VALUE_CHECK(p_field->data, 0xfff);
                break;
            case CTC_FIELD_KEY_IP_OPTIONS:
                CTC_MAX_VALUE_CHECK(p_field->data, 0x1);
                break;
            case CTC_FIELD_KEY_IP_PROTOCOL:
                CTC_MAX_VALUE_CHECK(p_field->data, 0xFF);
                break;
            case CTC_FIELD_KEY_IPV6_SA:
            case CTC_FIELD_KEY_IPV6_DA:
                CTC_PTR_VALID_CHECK(p_field->ext_data);
                if( (key_type == CTC_ACL_KEY_MAC_IPV4 || key_type == CTC_ACL_KEY_IPV4 || key_type == CTC_ACL_KEY_IPV4_EXT)
                 && (l3_type != CTC_PARSER_L3_TYPE_IPV6) )
                {
                    return CTC_E_INVALID_CONFIG;
                }
                break;
            case CTC_FIELD_KEY_ICMP_CODE:
            case CTC_FIELD_KEY_ICMP_TYPE:
                CTC_MAX_VALUE_CHECK(p_field->data, 0xff);
                break;
            case CTC_FIELD_KEY_UDF:
                CTC_PTR_VALID_CHECK(p_field->ext_data);
                CTC_MAX_VALUE_CHECK(((ctc_acl_udf_t*)p_field->ext_data)->udf_id, CTC_ASW_ACL_UDF_ENTRY_NUM - 1);
                break;
            case CTC_FIELD_KEY_L4_DST_PORT:
            case CTC_FIELD_KEY_L4_SRC_PORT:
                CTC_MAX_VALUE_CHECK(p_field->data, 0xffff);
                break;
            case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
            case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
            case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
            case CTC_FIELD_KEY_CVLAN_RANGE:
            case CTC_FIELD_KEY_SVLAN_RANGE:
                use_range_bmp = 1;
                CTC_MAX_VALUE_CHECK(p_field->data, CTC_ASW_ACL_RANGE_NUM - 1);
                break;
            case CTC_FIELD_KEY_TCP_FLAGS:
                CTC_MAX_VALUE_CHECK(p_field->data, 0x3F);
                break;
           case CTC_FIELD_KEY_L2_TYPE:
                CTC_MAX_VALUE_CHECK(p_field->data, CTC_PARSER_L2_TYPE_ETH_SNAP );
                break;
            case CTC_FIELD_KEY_IP_DSCP:
                CTC_MAX_VALUE_CHECK(p_field->data, CTC_MAX_QOS_DSCP_VALUE);
                break;
            default:
                break;
        }
    }
    if(key_type == CTC_ACL_KEY_MAC_IPV4 || key_type == CTC_ACL_KEY_MAC_IPV6 )
    {
        if( (CTC_BMP_ISSET(kset, CTC_FIELD_KEY_SVLAN_ID) && use_range_bmp)||
            ( CTC_BMP_ISSET(kset, CTC_FIELD_KEY_UDF) &&  ( CTC_BMP_ISSET(kset, CTC_FIELD_KEY_ETHER_TYPE)
                                                            || CTC_BMP_ISSET(kset, CTC_FIELD_KEY_STAG_COS) || CTC_BMP_ISSET(kset, CTC_FIELD_KEY_STAG_CFI))) )
        {
            CTC_ERROR_RETURN(CTC_E_PARAM_CONFLICT);
        }
    }
    else if(key_type == CTC_ACL_KEY_IPV6)
    {
        if((CTC_BMP_ISSET(kset, CTC_FIELD_KEY_L4_SRC_PORT) || CTC_BMP_ISSET(kset, CTC_FIELD_KEY_ICMP_CODE) || CTC_BMP_ISSET(kset, CTC_FIELD_KEY_ICMP_TYPE) )
            && use_range_bmp)
        {
            CTC_ERROR_RETURN(CTC_E_PARAM_CONFLICT);
        }
    }
    else if(key_type == CTC_ACL_KEY_MAC_EXT || key_type == CTC_ACL_KEY_UDF)
    {
        if(CTC_BMP_ISSET(kset, CTC_FIELD_KEY_UDF) && use_range_bmp)
        {
            CTC_ERROR_RETURN(CTC_E_PARAM_CONFLICT);
        }
    }
    if ((key_type == CTC_ACL_KEY_MAC_EXT) && (CTC_BMP_ISSET(kset, CTC_FIELD_KEY_MAC_DA)) && (CTC_BMP_ISSET(kset, CTC_FIELD_KEY_MAC_SA)))
    {
            return CTC_E_PARAM_CONFLICT;
    }
    if (key_type == CTC_ACL_KEY_MAC_IPV6 && (CTC_BMP_ISSET(kset, CTC_FIELD_KEY_IPV6_DA)) && (CTC_BMP_ISSET(kset, CTC_FIELD_KEY_IPV6_SA)))
    {
            return CTC_E_PARAM_CONFLICT;
    }
    return CTC_E_NONE;
}

#if 0
STATIC int32
_ctc_asw_acl_add_key_field(uint8 lchip, sys_acl_entry_t* pe, ctc_field_key_t* key_field, uint8 is_add)
{
    ds_t  remove_ext_data = {0};
    ds_t  ext_mask_temp   = {0};
    uint32 tmp_data = 0;
    uint32 tmp_mask = 0;

    /*check*/
    CTC_PTR_VALID_CHECK(key_field);

    if(is_add && key_field->ext_mask == NULL)
    {
        sal_memset(ext_mask_temp, 0xFF, sizeof(ds_t));
        key_field->ext_mask = ext_mask_temp;
    }

    if (key_field->type == CTC_FIELD_KEY_L3_TYPE)
    {
        _ctc_asw_acl_map_l3_type(key_field->data, &tmp_data);
        key_field->data = tmp_data;
    }
    else if (key_field->type == CTC_FIELD_KEY_L4_TYPE)
    {
        _ctc_asw_acl_map_l4_type(key_field->data, &tmp_data);
        key_field->data = tmp_data;
    }
    else if (key_field->type == CTC_FIELD_KEY_IP_FRAG)
    {
        _ctc_asw_acl_map_ip_frag(key_field->data, &tmp_data, &tmp_mask);
        key_field->data = tmp_data;
        key_field->mask = tmp_mask;
    }

    if ((!is_add) && (CTC_FIELD_KEY_PORT != key_field->type))
    {
        key_field->ext_data = remove_ext_data;
        key_field->ext_mask = remove_ext_data;
    }
    CTC_ERROR_RETURN(g_acl_build_key_func_cb[pe->key_type](lchip, key_field, pe, is_add));

    return CTC_E_NONE;
}
#endif

STATIC int32
_ctc_asw_acl_get_range_info(uint8 lchip, ctc_acl_range_t* range_info, uint8 index)
{
    uint32 cmd = 0;
    AclRangeCheck_m ds_range;

    cmd = DRV_IOR(AclRangeCheck_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &ds_range);

    if(!GetAclRangeCheck(V, valid_f, &ds_range))
    {
        return CTC_E_NOT_EXIST;
    }

    range_info->type = GetAclRangeCheck(V, optype_f, &ds_range);
    range_info->max = GetAclRangeCheck(V, maxVal_f, &ds_range);
    range_info->min = GetAclRangeCheck(V, minVal_f, &ds_range);

    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_update_range_bmp(uint8 lchip, uint16* range_bmp, uint8 index)
{
    uint8 i = 0;
    ctc_acl_range_t new_info;
    ctc_acl_range_t old_info;
    uint16 old_bmp = *range_bmp;
    
    CTC_ERROR_RETURN(_ctc_asw_acl_get_range_info(lchip, &new_info, index));
    if(CTC_IS_BIT_SET(old_bmp, index) || old_bmp == 0)
    {
        goto end;
    }

    for(i = 0; i < CTC_ASW_ACL_RANGE_NUM; i++)
    {
        if(!CTC_IS_BIT_SET(old_bmp, i))
        {
            continue;
        }
        _ctc_asw_acl_get_range_info(lchip, &old_info, i);
        if(old_info.type == new_info.type)
        {
            CTC_BIT_UNSET(old_bmp, i);
            break;
        }
    }

end:
    
CTC_BIT_SET(old_bmp, index);
    *range_bmp = old_bmp;
    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_get_compress_addr(uint8 lchip, ipv6_addr_t ipv6, uint32* addr_out, uint8 id_da)
{
    uint8 mode = 0;
    ctc_global_acl_property_t acl_prop;
    
    _ctc_asw_register_get_glb_acl_property(lchip, &acl_prop);
    mode = id_da ? acl_prop.key_ipv6_da_addr_mode : acl_prop.key_ipv6_sa_addr_mode;
    if(mode > 3)
    {
        return CTC_E_INVALID_CONFIG;
    }

    addr_out[0] = ipv6[mode];
    
    return CTC_E_NONE;
}


STATIC int32
__ctc_asw_acl_add_mackey160_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add)
{
    uint32 data = 0;
    uint32 mask = 0;
    sys_acl_buffer_t* p_buffer = NULL;
    hw_mac_addr_t hw_mac = {0};
    drv_acl_port_info_t pport_drv;
    uint16 range_bmp = 0;
    uint16 tmp_data = 0;
    uint16 tmp_mask = 0;

    p_buffer = &pe->buffer;

    if(is_add)
    {
        data = key_field->data;
        mask = key_field->mask;
    }

    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        CTC_ERROR_RETURN(_ctc_asw_acl_build_port_info(lchip, key_field, &pport_drv));
        SetKey160MacView0(V, sportBitmap_f, p_buffer->key, pport_drv.gport);
        SetKey160MacView0(V, sportBitmap_f, p_buffer->mask, pport_drv.gport_mask);
        SetKey160MacView0(V, portType_f, p_buffer->key, pport_drv.gport_type);
        SetKey160MacView0(V, portType_f, p_buffer->mask, pport_drv.gport_type_mask);
        break;
    case CTC_FIELD_KEY_ETHER_TYPE:
        SetKey160MacView0(V, ethtype_f, p_buffer->key, data);
        SetKey160MacView0(V, ethtype_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_MAC_SA:
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_data));
        SetKey160MacView0(A, sa_f, p_buffer->key, hw_mac);
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_mask));
        SetKey160MacView0(A, sa_f, p_buffer->mask, hw_mac);
        break;
    case CTC_FIELD_KEY_MAC_DA:
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_data));
        SetKey160MacView0(A, da_f, p_buffer->key, hw_mac);
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_mask));
        SetKey160MacView0(A, da_f, p_buffer->mask, hw_mac);
        break;
    case CTC_FIELD_KEY_STAG_VALID:
        SetKey160MacView0(V, stagStatus_f, p_buffer->key, data ? 1 : 0);
        SetKey160MacView0(V, stagStatus_f, p_buffer->mask, mask & 0x01);
        break;
    case CTC_FIELD_KEY_SVLAN_ID:
    case CTC_FIELD_KEY_STAG_COS:
    case CTC_FIELD_KEY_STAG_CFI:
        tmp_data = GetKey160MacView0(V, stag_f, p_buffer->key);
        tmp_mask = GetKey160MacView0(V, stag_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_SVLAN_ID)
        {
            tmp_data &= (~0xfff);
            tmp_mask &= (~0xfff);
            tmp_data |= (data & 0xfff);
            tmp_mask |= (mask & 0xfff);
        }
        else if (key_field->type == CTC_FIELD_KEY_STAG_COS)
        {
            tmp_data &= ~(0x7 << 13);
            tmp_mask &= ~(0x7 << 13);
            tmp_data |= ((data & 0x7) << 13);
            tmp_mask |= ((mask & 0x7) << 13);
        }
        else
        {

            tmp_data &= ~(0x1 << 12);
            tmp_mask &= ~(0x1 << 12);
            tmp_data |= ((data & 0x1) << 12);
            tmp_mask |= ((mask & 0x1) << 12);
        }
        SetKey160MacView0(V, stag_f, p_buffer->key, tmp_data);
        SetKey160MacView0(V, stag_f, p_buffer->mask, tmp_mask);
        break;

    case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
    case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
    case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
    case CTC_FIELD_KEY_CVLAN_RANGE:
    case CTC_FIELD_KEY_SVLAN_RANGE:
        range_bmp = GetKey160MacView0(V, rangeBitmap_f, p_buffer->key);
        CTC_ERROR_RETURN(_ctc_asw_acl_update_range_bmp(lchip, &range_bmp, data));
        SetKey160MacView0(V, rangeBitmap_f, p_buffer->key, range_bmp);
        SetKey160MacView0(V, rangeBitmap_f, p_buffer->mask, range_bmp);
        break;
    case CTC_FIELD_KEY_HASH_VALID:
        SetKey160MacView0(V, keyType_f, p_buffer->key, 0x0);
        SetKey160MacView0(V, keyType_f, p_buffer->mask, 0xf);
        SetKey160MacView0(V, valid_f, p_buffer->mask, 0x01);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
        break;
    }

    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_set_mac_mode(uint8 lchip, uint8 mode)
{
    uint32 cmd = 0;
    uint32 global_cfg = 0;
    cmd = DRV_IOR(AclGlobalKeyCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &global_cfg));

    SetAclGlobalKeyCtrl(V, macSel_f, &global_cfg, mode);

    cmd = DRV_IOW(AclGlobalKeyCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &global_cfg));
    return CTC_E_NONE;
}

STATIC int32
__ctc_asw_acl_add_macudfkey160_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add)
{
    uint32 data = 0;
    uint32 mask = 0;
    uint32 udf[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    uint32 udf_mask[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    ctc_acl_udf_t* p_udf = NULL;
    ctc_acl_udf_t* p_udf_mask = NULL;
    sys_acl_buffer_t* p_buffer = NULL;
    hw_mac_addr_t hw_mac = {0};
    drv_acl_port_info_t pport_drv;
    uint16 range_bmp = 0;

    p_buffer = &pe->buffer;

    if(is_add)
    {
        data = key_field->data;
        mask = key_field->mask;
    }

    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        CTC_ERROR_RETURN(_ctc_asw_acl_build_port_info(lchip, key_field, &pport_drv));
        SetKey160MacudfView0(V, sportBitmap_f, p_buffer->key, pport_drv.gport);
        SetKey160MacudfView0(V, sportBitmap_f, p_buffer->mask, pport_drv.gport_mask);
        SetKey160MacudfView0(V, portType_f, p_buffer->key, pport_drv.gport_type);
        SetKey160MacudfView0(V, portType_f, p_buffer->mask, pport_drv.gport_type_mask);
        break;
    case CTC_FIELD_KEY_ETHER_TYPE:
        SetKey160MacudfView0(V, ethtype_f, p_buffer->key, data);
        SetKey160MacudfView0(V, ethtype_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_MAC_SA:
    case CTC_FIELD_KEY_MAC_DA:
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_data));
        SetKey160MacudfView0(A, macAddr_f, p_buffer->key, hw_mac);
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_mask));
        SetKey160MacudfView0(A, macAddr_f, p_buffer->mask, hw_mac);
        SetKey160MacudfView0(V, isDa_f, p_buffer->key, (key_field->type == CTC_FIELD_KEY_MAC_DA)?1:0);
        SetKey160MacudfView0(V, isDa_f, p_buffer->mask, 1);
        CTC_ERROR_RETURN(_ctc_asw_acl_set_mac_mode(lchip, (key_field->type == CTC_FIELD_KEY_MAC_DA)));
        break;
    case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
    case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
    case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
    case CTC_FIELD_KEY_CVLAN_RANGE:
    case CTC_FIELD_KEY_SVLAN_RANGE:
        range_bmp = GetKey160MacudfView0(V, udf0_f, p_buffer->key) & 0xfff;
        CTC_ERROR_RETURN(_ctc_asw_acl_update_range_bmp(lchip, &range_bmp, data));
        SetKey160MacudfView0(V, udf0_f, p_buffer->key, range_bmp & 0xfff);
        SetKey160MacudfView0(V, udf0_f, p_buffer->mask, range_bmp & 0xfff);
        break;
    case CTC_FIELD_KEY_L4_TYPE:
        SetKey160MacudfView0(V, l4Type_f, p_buffer->key, data);
        SetKey160MacudfView0(V, l4Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L3_TYPE:
        SetKey160MacudfView0(V, l3Type_f, p_buffer->key, data);
        SetKey160MacudfView0(V, l3Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L2_TYPE:
        SetKey160MacudfView0(V, l2Type_f, p_buffer->key, data);
        SetKey160MacudfView0(V, l2Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_UDF:
        p_udf = (ctc_acl_udf_t*)key_field->ext_data;
        p_udf_mask = (ctc_acl_udf_t*)key_field->ext_mask;
        CTC_ASW_SET_HW_UDF(udf, p_udf->udf);
        CTC_ASW_SET_HW_UDF(udf_mask, p_udf_mask->udf);
        SetKey160MacudfView0(V, udfIndex_f, p_buffer->key, p_udf->udf_id);
        SetKey160MacudfView0(V, udfIndex_f, p_buffer->mask, 7);
        SetKey160MacudfView0(V, udf0_f, p_buffer->key, udf[0]);
        SetKey160MacudfView0(V, udf0_f, p_buffer->mask, udf_mask[0]);
        SetKey160MacudfView0(V, udf1_f, p_buffer->key, udf[1]);
        SetKey160MacudfView0(V, udf1_f, p_buffer->mask, udf_mask[1]);
        SetKey160MacudfView0(V, udf01Valid_f, p_buffer->key, 3);
        SetKey160MacudfView0(V, udf01Valid_f, p_buffer->mask, 3);
        break;
    case CTC_FIELD_KEY_HASH_VALID:
        SetKey160MacudfView0(V, keyType_f, p_buffer->key, 0x1);
        SetKey160MacudfView0(V, keyType_f, p_buffer->mask, 0xf);
        SetKey160MacudfView0(V, valid_f, p_buffer->mask, 0x01);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
        break;
    }

    return CTC_E_NONE;
}


STATIC int32
__ctc_asw_acl_add_ethudfkey160_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add)
{
    uint32 data = 0;
    uint32 mask = 0;
    uint32 udf[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    uint32 udf_mask[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    ctc_acl_udf_t* p_udf = NULL;
    ctc_acl_udf_t* p_udf_mask = NULL;
    sys_acl_buffer_t* p_buffer = NULL;
    drv_acl_port_info_t pport_drv;
    uint16 range_bmp = 0;

    p_buffer = &pe->buffer;

    if(is_add)
    {
        data = key_field->data;
        mask = key_field->mask;
    }

    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        CTC_ERROR_RETURN(_ctc_asw_acl_build_port_info(lchip, key_field, &pport_drv));
        SetKey160EthudfView0(V, sportBitmap_f, p_buffer->key, pport_drv.gport);
        SetKey160EthudfView0(V, sportBitmap_f, p_buffer->mask, pport_drv.gport_mask);
        SetKey160EthudfView0(V, portType_f, p_buffer->key, pport_drv.gport_type);
        SetKey160EthudfView0(V, portType_f, p_buffer->mask, pport_drv.gport_type_mask);
        break;
    case CTC_FIELD_KEY_L4_TYPE:
        SetKey160EthudfView0(V, l4Type_f, p_buffer->key, data);
        SetKey160EthudfView0(V, l4Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L3_TYPE:
        SetKey160EthudfView0(V, l3Type_f, p_buffer->key, data);
        SetKey160EthudfView0(V, l3Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L2_TYPE:
        SetKey160EthudfView0(V, l2Type_f, p_buffer->key, data);
        SetKey160EthudfView0(V, l2Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
    case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
    case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
    case CTC_FIELD_KEY_CVLAN_RANGE:
    case CTC_FIELD_KEY_SVLAN_RANGE:
        range_bmp = GetKey160MacudfView0(V, udf0_f, p_buffer->key) & 0xfff;
        CTC_ERROR_RETURN(_ctc_asw_acl_update_range_bmp(lchip, &range_bmp, data));
        SetKey160EthudfView0(V, udf0_f, p_buffer->key, range_bmp & 0xfff);
        SetKey160EthudfView0(V, udf0_f, p_buffer->mask, range_bmp & 0xfff);
        break;
    case CTC_FIELD_KEY_HASH_VALID:
        SetKey160EthudfView0(V, keyType_f, p_buffer->key, 0x8);
        SetKey160EthudfView0(V, keyType_f, p_buffer->mask, 0xf);
        SetKey160EthudfView0(V, valid_f, p_buffer->mask, 0x01);
        break;
    case CTC_FIELD_KEY_UDF:
        p_udf = (ctc_acl_udf_t*)key_field->ext_data;
        p_udf_mask = (ctc_acl_udf_t*)key_field->ext_mask;
        CTC_ASW_SET_HW_UDF(udf, p_udf->udf);
        CTC_ASW_SET_HW_UDF(udf_mask, p_udf_mask->udf);
        SetKey160EthudfView0(V, udfIndex_f, p_buffer->key, p_udf->udf_id);
        SetKey160EthudfView0(V, udfIndex_f, p_buffer->mask, 7);
        SetKey160EthudfView0(V, udf0_f, p_buffer->key, udf[0]);
        SetKey160EthudfView0(V, udf0_f, p_buffer->mask, udf_mask[0]);
        SetKey160EthudfView0(V, udf1_f, p_buffer->key, udf[1]);
        SetKey160EthudfView0(V, udf1_f, p_buffer->mask, udf_mask[1]);
        SetKey160EthudfView0(V, udf2_f, p_buffer->key, udf[2]);
        SetKey160EthudfView0(V, udf2_f, p_buffer->mask, udf_mask[2]);
        SetKey160EthudfView0(V, udf3_f, p_buffer->key, udf[3]);
        SetKey160EthudfView0(V, udf3_f, p_buffer->mask, udf_mask[3]);
        SetKey160EthudfView0(V, udfValid_f, p_buffer->key, 0xf);
        SetKey160EthudfView0(V, udfValid_f, p_buffer->mask, 0xf);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

STATIC int32
__ctc_asw_acl_add_macipudfkey320_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add)
{
    uint32 data = 0;
    uint32 mask = 0;
    uint32 udf[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    uint32 udf_mask[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    ipv6_addr_t hw_ip6 = {0};
    ctc_acl_udf_t* p_udf = NULL;
    ctc_acl_udf_t* p_udf_mask = NULL;
    sys_acl_buffer_t* p_buffer = NULL;
    hw_mac_addr_t hw_mac = {0};
    drv_acl_port_info_t pport_drv;
    uint16 range_bmp = 0;
    uint16 tmp_data = 0;
    uint16 tmp_mask = 0;

    p_buffer = &pe->buffer;

    if(is_add)
    {
        data = key_field->data;
        mask = key_field->mask;
    }

    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        CTC_ERROR_RETURN(_ctc_asw_acl_build_port_info(lchip, key_field, &pport_drv));
        SetKey320MacipudfView0(V, sportBitmap_f, p_buffer->key, pport_drv.gport);
        SetKey320MacipudfView0(V, sportBitmap_f, p_buffer->mask, pport_drv.gport_mask);
        SetKey320MacipudfView0(V, portType_f, p_buffer->key, pport_drv.gport_type);
        SetKey320MacipudfView0(V, portType_f, p_buffer->mask, pport_drv.gport_type_mask);
        break;
    case CTC_FIELD_KEY_L4_TYPE:
        SetKey320MacipudfView0(V, l4Type_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, l4Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L3_TYPE:
        SetKey320MacipudfView0(V, l3Type_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, l3Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_MAC_SA:
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_data));
        SetKey320MacipudfView0(A, sa0_f, p_buffer->key, hw_mac);
        data = (hw_mac[1]&0xE000)>>13;
        SetKey320MacipudfView0(V, sa1_f, p_buffer->key, data);
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_mask));
        SetKey320MacipudfView0(A, sa0_f, p_buffer->mask, hw_mac);
        SetKey320MacipudfView0(V, sa1_f, p_buffer->mask, ((hw_mac[1]&0xE000)>>13)&0x7);
        break;
    case CTC_FIELD_KEY_MAC_DA:
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_data));
        SetKey320MacipudfView0(A, da_f, p_buffer->key, hw_mac);
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_mask));
        SetKey320MacipudfView0(A, da_f, p_buffer->mask, hw_mac);
        break;
    case CTC_FIELD_KEY_IP_DSCP:
        SetKey320MacipudfView0(V, tos_f, p_buffer->key, data << 2);
        SetKey320MacipudfView0(V, tos_f, p_buffer->mask, mask << 2);
        break;
    case CTC_FIELD_KEY_STAG_VALID:
        SetKey320MacipudfView0(V, stagStatus_f, p_buffer->key, data ? 1 : 0);
        SetKey320MacipudfView0(V, stagStatus_f, p_buffer->mask, mask & 0x01);
        break;
    case CTC_FIELD_KEY_SVLAN_ID:
        SetKey320MacipudfView0(V, svid_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, svid_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L4_DST_PORT:
        SetKey320MacipudfView0(V, l4Dport_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, l4Dport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_ICMP_CODE:
    case CTC_FIELD_KEY_ICMP_TYPE:
        tmp_data = GetKey320MacipudfView0(V, l4Sport_f, p_buffer->key);
        tmp_mask = GetKey320MacipudfView0(V, l4Sport_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_ICMP_TYPE)
        {
            tmp_data &= (0x00ff);
            tmp_mask &= (0x00ff);
            tmp_data |= ((data << 8)&0xff00);
            tmp_mask |=((mask << 8)&0xff00);
        }
        else
        {
            tmp_data &= (0xff00);
            tmp_mask &= (0xff00);
            tmp_data |= (data & 0xff);
            tmp_mask |= (mask & 0xff);
        }
        data = tmp_data;
        mask = tmp_mask;
    case CTC_FIELD_KEY_L4_SRC_PORT:
        SetKey320MacipudfView0(V, l4Sport_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, l4Sport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_TCP_FLAGS:
        SetKey320MacipudfView0(V, tcpFlag_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, tcpFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_FRAG:
        SetKey320MacipudfView0(V, fragmentFlag_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, fragmentFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_OPTIONS:
        SetKey320MacipudfView0(V, ipOption_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, ipOption_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PROTOCOL:
        SetKey320MacipudfView0(V, ipProtocol_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, ipProtocol_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_SA:
        SetKey320MacipudfView0(V, sip_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, sip_f, p_buffer->mask, mask);
        SetKey320MacipudfView0(V, l3Type_f, p_buffer->key, 0x1);
        SetKey320MacipudfView0(V, l3Type_f, p_buffer->mask, 0x7);
        break;
    case CTC_FIELD_KEY_IP_DA:
        SetKey320MacipudfView0(V, dip_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, dip_f, p_buffer->mask, mask);
        SetKey320MacipudfView0(V, l3Type_f, p_buffer->key, 0x1);
        SetKey320MacipudfView0(V, l3Type_f, p_buffer->mask, 0x7);
        break;
    case CTC_FIELD_KEY_IPV6_SA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        _ctc_asw_acl_get_compress_addr(lchip, hw_ip6, &data, 0);
        SetKey320MacipudfView0(V, sip_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, sip_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IPV6_DA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        _ctc_asw_acl_get_compress_addr(lchip, hw_ip6, &data, 1);
        SetKey320MacipudfView0(V, dip_f, p_buffer->key, data);
        SetKey320MacipudfView0(V, dip_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
    case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
    case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
    case CTC_FIELD_KEY_CVLAN_RANGE:
    case CTC_FIELD_KEY_SVLAN_RANGE:
        range_bmp = GetKey320MacipudfView0(V, svid_f, p_buffer->key);
        CTC_ERROR_RETURN(_ctc_asw_acl_update_range_bmp(lchip, &range_bmp, data));
        SetKey320MacipudfView0(V, svid_f, p_buffer->key, range_bmp & 0xfff);
        SetKey320MacipudfView0(V, svid_f, p_buffer->mask, 0xfff);
        break;
    case CTC_FIELD_KEY_HASH_VALID:
        SetKey320MacipudfView0(V, keyType_f, p_buffer->key, 0x3);
        SetKey320MacipudfView0(V, keyType_f, p_buffer->mask, 0xf);
        SetKey320MacipudfView0(V, valid_f, p_buffer->mask, 0x01);
        SetKey320MacipudfView0(V, valid0_f, p_buffer->mask, 0x01);
        break;
    case CTC_FIELD_KEY_UDF:
        p_udf = (ctc_acl_udf_t*)key_field->ext_data;
        p_udf_mask = (ctc_acl_udf_t*)key_field->ext_mask;
        CTC_ASW_SET_HW_UDF(udf, p_udf->udf);
        CTC_ASW_SET_HW_UDF(udf_mask, p_udf_mask->udf);
        SetKey320MacipudfView0(V, udfIndex_f, p_buffer->key, p_udf->udf_id);
        SetKey320MacipudfView0(V, udfIndex_f, p_buffer->mask, 7);
        SetKey320MacipudfView0(V, udf0_f, p_buffer->key, udf[0]);
        SetKey320MacipudfView0(V, udf0_f, p_buffer->mask, udf_mask[0]);
        SetKey320MacipudfView0(V, udf1_f, p_buffer->key, udf[1]);
        SetKey320MacipudfView0(V, udf1_f, p_buffer->mask, udf_mask[1]);
        SetKey320MacipudfView0(V, udf01Valid_f, p_buffer->key, 3);
        SetKey320MacipudfView0(V, udf01Valid_f, p_buffer->mask, 3);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

STATIC int32
__ctc_asw_acl_add_ipkey160_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add)
{
    uint32 data = 0;
    uint32 mask = 0;
    sys_acl_buffer_t* p_buffer = NULL;
    drv_acl_port_info_t pport_drv;
    ipv6_addr_t hw_ip6 = {0};
    uint16 range_bmp = 0;
    uint16 tmp_data = 0;
    uint16 tmp_mask = 0;

    p_buffer = &pe->buffer;

    if(is_add)
    {
        data = key_field->data;
        mask = key_field->mask;
    }

    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        CTC_ERROR_RETURN(_ctc_asw_acl_build_port_info(lchip, key_field, &pport_drv));
        SetKey160IpView0(V, sportBitmap_f, p_buffer->key, pport_drv.gport);
        SetKey160IpView0(V, sportBitmap_f, p_buffer->mask, pport_drv.gport_mask);
        SetKey160IpView0(V, portType_f, p_buffer->key, pport_drv.gport_type);
        SetKey160IpView0(V, portType_f, p_buffer->mask, pport_drv.gport_type_mask);
        break;
    case CTC_FIELD_KEY_L4_TYPE:
        SetKey160IpView0(V, l4Type_f, p_buffer->key, data);
        SetKey160IpView0(V, l4Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L3_TYPE:
        SetKey160IpView0(V, l3Type_f, p_buffer->key, data);
        SetKey160IpView0(V, l3Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L4_DST_PORT:
        SetKey160IpView0(V, l4Dport_f, p_buffer->key, data);
        SetKey160IpView0(V, l4Dport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_ICMP_CODE:
    case CTC_FIELD_KEY_ICMP_TYPE:
        tmp_data = GetKey160IpView0(V, l4Sport_f, p_buffer->key);
        tmp_mask = GetKey160IpView0(V, l4Sport_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_ICMP_TYPE)
        {
            tmp_data &= (0x00ff);
            tmp_mask &= (0x00ff);
            tmp_data |= ((data << 8)&0xff00);
            tmp_mask |=((mask << 8)&0xff00);
        }
        else
        {
            tmp_data &= (0xff00);
            tmp_mask &= (0xff00);
            tmp_data |= (data & 0xff);
            tmp_mask |= (mask & 0xff);
        }
        data = tmp_data;
        mask = tmp_mask;
    case CTC_FIELD_KEY_L4_SRC_PORT:
        SetKey160IpView0(V, l4Sport_f, p_buffer->key, data);
        SetKey160IpView0(V, l4Sport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_TCP_FLAGS:
        SetKey160IpView0(V, tcpFlag_f, p_buffer->key, data);
        SetKey160IpView0(V, tcpFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_FRAG:
        SetKey160IpView0(V, fragmentFlag_f, p_buffer->key, data);
        SetKey160IpView0(V, fragmentFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_OPTIONS:
        SetKey160IpView0(V, ipOption_f, p_buffer->key, data);
        SetKey160IpView0(V, ipOption_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PROTOCOL:
        SetKey160IpView0(V, ipProtocol_f, p_buffer->key, data);
        SetKey160IpView0(V, ipProtocol_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_DSCP:
        SetKey160IpView0(V, tos_f, p_buffer->key, data << 2);
        SetKey160IpView0(V, tos_f, p_buffer->mask, mask << 2);
        break;
    case CTC_FIELD_KEY_IP_SA:
        SetKey160IpView0(V, sip_f, p_buffer->key, data);
        SetKey160IpView0(V, sip_f, p_buffer->mask, mask);
        SetKey160IpView0(V, l3Type_f, p_buffer->key, 0x1);
        SetKey160IpView0(V, l3Type_f, p_buffer->mask, 0x7);
        break;
    case CTC_FIELD_KEY_IP_DA:
        SetKey160IpView0(V, dip_f, p_buffer->key, data);
        SetKey160IpView0(V, dip_f, p_buffer->mask, mask);
        SetKey160IpView0(V, l3Type_f, p_buffer->key, 0x1);
        SetKey160IpView0(V, l3Type_f, p_buffer->mask, 0x7);
        break;
    case CTC_FIELD_KEY_IPV6_SA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        _ctc_asw_acl_get_compress_addr(lchip, hw_ip6, &data, 0);
        SetKey160IpView0(V, sip_f, p_buffer->key, data);
        SetKey160IpView0(V, sip_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IPV6_DA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        _ctc_asw_acl_get_compress_addr(lchip, hw_ip6, &data, 1);
        SetKey160IpView0(V, dip_f, p_buffer->key, data);
        SetKey160IpView0(V, dip_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
    case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
    case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
    case CTC_FIELD_KEY_CVLAN_RANGE:
    case CTC_FIELD_KEY_SVLAN_RANGE:
        range_bmp = GetKey160IpView0(V, rangeBitmap_f, p_buffer->key);
        CTC_ERROR_RETURN(_ctc_asw_acl_update_range_bmp(lchip, &range_bmp, data));
        SetKey160IpView0(V, rangeBitmap_f, p_buffer->key, range_bmp & 0xfff);
        SetKey160IpView0(V, rangeBitmap_f, p_buffer->mask, range_bmp & 0xfff);
        break;
    case CTC_FIELD_KEY_HASH_VALID:
        SetKey160IpView0(V, keyType_f, p_buffer->key, 0x2);
        SetKey160IpView0(V, keyType_f, p_buffer->mask, 0xf);
        SetKey160IpView0(V, valid_f, p_buffer->mask, 0x01);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}


STATIC int32
__ctc_asw_acl_add_ipudfkey320_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add)
{
    uint32 data = 0;
    uint32 mask = 0;
    uint32 udf[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    uint32 udf_mask[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    ctc_acl_udf_t* p_udf = NULL;
    ctc_acl_udf_t* p_udf_mask = NULL;
    sys_acl_buffer_t* p_buffer = NULL;
    ipv6_addr_t hw_ip6 = {0};
    uint16 range_bmp = 0;
    uint16 tmp_data = 0;
    uint16 tmp_mask = 0;
    drv_acl_port_info_t port_drv;

    p_buffer = &pe->buffer;

    if(is_add)
    {
        data = key_field->data;
        mask = key_field->mask;
    }

    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        CTC_ERROR_RETURN(_ctc_asw_acl_build_port_info(lchip, key_field, &port_drv));
        SetKey320IpudfView0(V, sportBitmap_f, p_buffer->key, port_drv.gport);
        SetKey320IpudfView0(V, sportBitmap_f, p_buffer->mask, port_drv.gport_mask);
        SetKey320IpudfView0(V, portType_f, p_buffer->key, port_drv.gport_type);
        SetKey320IpudfView0(V, portType_f, p_buffer->mask, port_drv.gport_type_mask);
        break;
    case CTC_FIELD_KEY_L4_TYPE:
        SetKey320IpudfView0(V, l4Type_f, p_buffer->key, data);
        SetKey320IpudfView0(V, l4Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L3_TYPE:
        SetKey320IpudfView0(V, l3Type_f, p_buffer->key, data);
        SetKey320IpudfView0(V, l3Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_ETHER_TYPE:
        SetKey320IpudfView0(V, ethtype_f, p_buffer->key, data);
        SetKey320IpudfView0(V, ethtype_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_STAG_VALID:
        SetKey320IpudfView0(V, stagStatus_f, p_buffer->key, data ? 1 :0);
        SetKey320IpudfView0(V, stagStatus_f, p_buffer->mask, mask & 0x01);
        break;
    case CTC_FIELD_KEY_SVLAN_ID:
        SetKey320IpudfView0(V, svid_f, p_buffer->key, data);
        SetKey320IpudfView0(V, svid_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L4_DST_PORT:
        SetKey320IpudfView0(V, l4Dport_f, p_buffer->key, data);
        SetKey320IpudfView0(V, l4Dport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_ICMP_CODE:
    case CTC_FIELD_KEY_ICMP_TYPE:
        tmp_data = GetKey320IpudfView0(V, l4Sport_f, p_buffer->key);
        tmp_mask = GetKey320IpudfView0(V, l4Sport_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_ICMP_TYPE)
        {
            tmp_data &= (0x00ff);
            tmp_mask &= (0x00ff);
            tmp_data |= ((data << 8)&0xff00);
            tmp_mask |=((mask << 8)&0xff00);
        }
        else
        {
            tmp_data &= (0xff00);
            tmp_mask &= (0xff00);
            tmp_data |= (data & 0xff);
            tmp_mask |= (mask & 0xff);
        }
        data = tmp_data;
        mask = tmp_mask;
    case CTC_FIELD_KEY_L4_SRC_PORT:
        SetKey320IpudfView0(V, l4Sport_f, p_buffer->key, data);
        SetKey320IpudfView0(V, l4Sport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_TCP_FLAGS:
        SetKey320IpudfView0(V, tcpFlag_f, p_buffer->key, data);
        SetKey320IpudfView0(V, tcpFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_FRAG:
        SetKey320IpudfView0(V, fragmentFlag_f, p_buffer->key, data);
        SetKey320IpudfView0(V, fragmentFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_OPTIONS:
        SetKey320IpudfView0(V, ipOption_f, p_buffer->key, data);
        SetKey320IpudfView0(V, ipOption_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PROTOCOL:
        SetKey320IpudfView0(V, ipProtocol_f, p_buffer->key, data);
        SetKey320IpudfView0(V, ipProtocol_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_DSCP:
        SetKey320IpudfView0(V, tos_f, p_buffer->key, data << 2);
        SetKey320IpudfView0(V, tos_f, p_buffer->mask, mask << 2);
        break;
    case CTC_FIELD_KEY_IP_SA:
        SetKey320IpudfView0(V, sip_f, p_buffer->key, data);
        SetKey320IpudfView0(V, sip_f, p_buffer->mask, mask);
        SetKey320IpudfView0(V, l3Type_f, p_buffer->key, 0x1);
        SetKey320IpudfView0(V, l3Type_f, p_buffer->mask, 0x7);
        break;
    case CTC_FIELD_KEY_IP_DA:
        SetKey320IpudfView0(V, dip_f, p_buffer->key, data);
        SetKey320IpudfView0(V, dip_f, p_buffer->mask, mask);
        SetKey320IpudfView0(V, l3Type_f, p_buffer->key, 0x1);
        SetKey320IpudfView0(V, l3Type_f, p_buffer->mask, 0x7);
        break;
    case CTC_FIELD_KEY_IPV6_SA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        _ctc_asw_acl_get_compress_addr(lchip, hw_ip6, &data, 0);
        SetKey320IpudfView0(V, sip_f, p_buffer->key, data);
        SetKey320IpudfView0(V, sip_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IPV6_DA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        _ctc_asw_acl_get_compress_addr(lchip, hw_ip6, &data, 1);
        SetKey320IpudfView0(V, dip_f, p_buffer->key, data);
        SetKey320IpudfView0(V, dip_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
    case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
    case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
    case CTC_FIELD_KEY_CVLAN_RANGE:
    case CTC_FIELD_KEY_SVLAN_RANGE:
        range_bmp = GetKey320IpudfView0(V, rangeBitmap_f, p_buffer->key);
        CTC_ERROR_RETURN(_ctc_asw_acl_update_range_bmp(lchip, &range_bmp, data));
        SetKey320IpudfView0(V, rangeBitmap_f, p_buffer->key, range_bmp & 0xfff);
        SetKey320IpudfView0(V, rangeBitmap_f, p_buffer->mask, range_bmp & 0xfff);
        break;
    case CTC_FIELD_KEY_HASH_VALID:
        SetKey320IpudfView0(V, keyType_f, p_buffer->key, 0x4);
        SetKey320IpudfView0(V, keyType_f, p_buffer->mask, 0xf);
        SetKey320IpudfView0(V, valid_f, p_buffer->mask, 0x01);
        SetKey320IpudfView0(V, valid0_f, p_buffer->mask, 0x01);
        break;
    case CTC_FIELD_KEY_UDF:
        p_udf = (ctc_acl_udf_t*)key_field->ext_data;
        p_udf_mask = (ctc_acl_udf_t*)key_field->ext_mask;
        CTC_ASW_SET_HW_UDF(udf, p_udf->udf);
        CTC_ASW_SET_HW_UDF(udf_mask, p_udf_mask->udf);
        SetKey320IpudfView0(V, udfIndex_f, p_buffer->key, p_udf->udf_id);
        SetKey320IpudfView0(V, udfIndex_f, p_buffer->mask, 7);
        SetKey320IpudfView0(V, udf0_f, p_buffer->key, udf[0]);
        SetKey320IpudfView0(V, udf0_f, p_buffer->mask, udf_mask[0]);
        SetKey320IpudfView0(V, udf1_f, p_buffer->key, udf[1]);
        SetKey320IpudfView0(V, udf1_f, p_buffer->mask, udf_mask[1]);
        SetKey320IpudfView0(V, udf2_f, p_buffer->key, udf[2]);
        SetKey320IpudfView0(V, udf2_f, p_buffer->mask, udf_mask[2]);
        SetKey320IpudfView0(V, udf3_f, p_buffer->key, udf[3]);
        SetKey320IpudfView0(V, udf3_f, p_buffer->mask, udf_mask[3]);
        SetKey320IpudfView0(V, udfValid_f, p_buffer->key, 0xf);
        SetKey320IpudfView0(V, udfValid_f, p_buffer->mask, 0xf);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

#if 0
STATIC int32
_ctc_asw_acl_set_ipv6_addr_mode(uint8 lchip, uint8 mode)
{
    uint32 cmd = 0;
    uint32 global_cfg = 0;
    cmd = DRV_IOR(AclGlobalKeyCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &global_cfg));

    SetAclGlobalKeyCtrl(V, ipv6Addr1Mode_f, &global_cfg, mode);
    SetAclGlobalKeyCtrl(V, ipv6Addr2Mode_f, &global_cfg, mode);

    cmd = DRV_IOW(AclGlobalKeyCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &global_cfg));
    return CTC_E_NONE;
}
#endif

STATIC int32
__ctc_asw_acl_add_macipv6key640_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add)
{
    uint32 data = 0;
    uint32 mask = 0;
    ipv6_addr_t hw_ip6 = {0};
    ipv6_addr_t hw_ip6_mask = {0};
    sys_acl_buffer_t* p_buffer = NULL;
    hw_mac_addr_t hw_mac = {0};
    drv_acl_port_info_t port_drv = {0};
    uint16 range_bmp = 0;
    uint16 tmp_data = 0;
    uint16 tmp_mask = 0;

    p_buffer = &pe->buffer;

    if(is_add)
    {
        data = key_field->data;
        mask = key_field->mask;
    }

    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        CTC_ERROR_RETURN(_ctc_asw_acl_build_port_info(lchip, key_field, &port_drv));
        SetKey640Macipv6View0(V, sportBitmap_f, p_buffer->key, port_drv.gport);
        SetKey640Macipv6View0(V, sportBitmap_f, p_buffer->mask, port_drv.gport_mask);
        SetKey640Macipv6View0(V, portType_f, p_buffer->key, port_drv.gport_type);
        SetKey640Macipv6View0(V, portType_f, p_buffer->mask, port_drv.gport_type_mask);
        break;
    case CTC_FIELD_KEY_L4_TYPE:
        SetKey640Macipv6View0(V, l4Type_f, p_buffer->key, data);
        SetKey640Macipv6View0(V, l4Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L3_TYPE:
        SetKey640Macipv6View0(V, l3Type_f, p_buffer->key, data);
        SetKey640Macipv6View0(V, l3Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_MAC_SA:
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_data));
        SetKey640Macipv6View0(A, sa_f, p_buffer->key, hw_mac);
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_mask));
        SetKey640Macipv6View0(A, sa_f, p_buffer->mask, hw_mac);
        break;
    case CTC_FIELD_KEY_MAC_DA:
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_data));
        SetKey640Macipv6View0(A, da_f, p_buffer->key, hw_mac);
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_mask));
        SetKey640Macipv6View0(A, da_f, p_buffer->mask, hw_mac);
        break;
    case CTC_FIELD_KEY_STAG_VALID:
        SetKey640Macipv6View0(V, stagStatus_f, p_buffer->key, data ? 1 : 0);
        SetKey640Macipv6View0(V, stagStatus_f, p_buffer->mask, mask & 0x01);
        break;
    case CTC_FIELD_KEY_CTAG_VALID:
        SetKey640Macipv6View0(V, ctagStatus_f, p_buffer->key, data ? 1 : 0);
        SetKey640Macipv6View0(V, ctagStatus_f, p_buffer->mask, mask & 0x01);
        break;
    case CTC_FIELD_KEY_SVLAN_ID:
    case CTC_FIELD_KEY_STAG_COS:
    case CTC_FIELD_KEY_STAG_CFI:
        tmp_data = GetKey640Macipv6View0(V, stag_f, p_buffer->key);
        tmp_mask = GetKey640Macipv6View0(V, stag_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_SVLAN_ID)
        {
            tmp_data &= (~0xfff);
            tmp_mask &= (~0xfff);
            tmp_data |= (data & 0xfff);
            tmp_mask |= (mask & 0xfff);
        }
        else if (key_field->type == CTC_FIELD_KEY_STAG_COS)
        {
            tmp_data &= ~(0x7 << 13);
            tmp_mask &= ~(0x7 << 13);
            tmp_data |= ((data & 0x7) << 13);
            tmp_mask |= ((mask & 0x7) << 13);
        }
        else
        {

            tmp_data &= ~(0x1 << 12);
            tmp_mask &= ~(0x1 << 12);
            tmp_data |= ((data & 0x1) << 12);
            tmp_mask |= ((mask & 0x1) << 12);
        }
        SetKey640Macipv6View0(V, stag_f, p_buffer->key, tmp_data);
        SetKey640Macipv6View0(V, stag_f, p_buffer->mask, tmp_mask);
        break;
    case CTC_FIELD_KEY_L4_DST_PORT:
        SetKey640Macipv6View0(V, l4Dport_f, p_buffer->key, data);
        SetKey640Macipv6View0(V, l4Dport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_ICMP_CODE:
    case CTC_FIELD_KEY_ICMP_TYPE:
        tmp_data = GetKey640Macipv6View0(V, l4Sport_f, p_buffer->key);
        tmp_mask = GetKey640Macipv6View0(V, l4Sport_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_ICMP_TYPE)
        {
            tmp_data &= (0x00ff);
            tmp_mask &= (0x00ff);
            tmp_data |= ((data << 8)&0xff00);
            tmp_mask |=((mask << 8)&0xff00);
        }
        else
        {
            tmp_data &= (0xff00);
            tmp_mask &= (0xff00);
            tmp_data |= (data & 0xff);
            tmp_mask |= (mask & 0xff);
        }
        data = tmp_data;
        mask = tmp_mask;
    case CTC_FIELD_KEY_L4_SRC_PORT:
        SetKey640Macipv6View0(V, l4Sport_f, p_buffer->key, data);
        SetKey640Macipv6View0(V, l4Sport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_TCP_FLAGS:
        SetKey640Macipv6View0(V, tcpFlag_f, p_buffer->key, data);
        SetKey640Macipv6View0(V, tcpFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_FRAG:
        SetKey640Macipv6View0(V, fragmentFlag_f, p_buffer->key, data);
        SetKey640Macipv6View0(V, fragmentFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_OPTIONS:
        SetKey640Macipv6View0(V, ipOption_f, p_buffer->key, data);
        SetKey640Macipv6View0(V, ipOption_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PROTOCOL:
        SetKey640Macipv6View0(V, ipProtocol_f, p_buffer->key, data);
        SetKey640Macipv6View0(V, ipProtocol_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_DSCP:
        SetKey640Macipv6View0(V, tos_f, p_buffer->key, data << 2);
        SetKey640Macipv6View0(V, tos_f, p_buffer->mask, mask << 2);
        break;
    case CTC_FIELD_KEY_IPV6_SA:
    case CTC_FIELD_KEY_IPV6_DA:
    {
        uint8 add1_match = 0, add2_match = 0;
        ctc_global_acl_property_t acl_prop;
        _ctc_asw_register_get_glb_acl_property(lchip, &acl_prop);
        add1_match = (acl_prop.mac_ipv6_key_u0_mode == (key_field->type == CTC_FIELD_KEY_IPV6_DA)) ? 1 : 0;
        add2_match = (acl_prop.mac_ipv6_key_u1_mode == (key_field->type == CTC_FIELD_KEY_IPV6_DA)) ? 1 : 0;

        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        CTC_ASW_REVERT_IP6(hw_ip6_mask, (uint32*)key_field->ext_mask);
        if(add1_match)
        {
            SetKey640Macipv6View0(A, ipaddr10_f, p_buffer->key, &hw_ip6[0]);
            data = (hw_ip6[1]>>16)&0xFFFF;
            SetKey640Macipv6View0(V, ipaddr11_f,  p_buffer->key, data);

            SetKey640Macipv6View0(A, ipaddr10_f, p_buffer->mask, &hw_ip6_mask[0]);
            data = (hw_ip6_mask[1]>>16)&0xFFFF;
            SetKey640Macipv6View0(V, ipaddr11_f, p_buffer->mask, data);
        }
        if(add2_match)
        {
            SetKey640Macipv6View0(A, ipaddr2_f, p_buffer->key, &hw_ip6[2]);
            SetKey640Macipv6View0(A, ipaddr2_f, p_buffer->mask, &hw_ip6_mask[2]);
        }
    }
        break;
    case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
    case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
    case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
    case CTC_FIELD_KEY_CVLAN_RANGE:
    case CTC_FIELD_KEY_SVLAN_RANGE:
        range_bmp = GetKey640Macipv6View0(V, stag_f, p_buffer->key);
        CTC_ERROR_RETURN(_ctc_asw_acl_update_range_bmp(lchip, &range_bmp, data));
        SetKey640Macipv6View0(V, stag_f, p_buffer->key, range_bmp & 0xffff);
        SetKey640Macipv6View0(V, stag_f, p_buffer->mask, range_bmp & 0xffff);
        break;
    case CTC_FIELD_KEY_HASH_VALID:
        SetKey640Macipv6View0(V, keyType_f, p_buffer->key, 0x5);
        SetKey640Macipv6View0(V, keyType_f, p_buffer->mask, 0x0f);
        SetKey640Macipv6View0(V, valid_f, p_buffer->mask, 0x01);
        SetKey640Macipv6View0(V, valid0_f, p_buffer->mask, 0x01);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}


STATIC int32
__ctc_asw_acl_add_ipv6key320_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add)
{
    uint32 data = 0;
    uint32 mask = 0;
    sys_acl_buffer_t* p_buffer = NULL;
    uint16 range_bmp = 0;
    drv_acl_port_info_t port_drv = {0};
    ipv6_addr_t hw_ip6 = {0};
    uint16 tmp_data = 0;
    uint16 tmp_mask = 0;

    p_buffer = &pe->buffer;

    if(is_add)
    {
        data = key_field->data;
        mask = key_field->mask;
    }

    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        CTC_ERROR_RETURN(_ctc_asw_acl_build_port_info(lchip, key_field, &port_drv));
        SetKey320Ipv6View0(V, sportBitmap_f, p_buffer->key, port_drv.gport);
        SetKey320Ipv6View0(V, sportBitmap_f, p_buffer->mask, port_drv.gport_mask);
        SetKey320Ipv6View0(V, portType_f, p_buffer->key, port_drv.gport_type);
        SetKey320Ipv6View0(V, portType_f, p_buffer->mask, port_drv.gport_type_mask);
        break;
    case CTC_FIELD_KEY_L4_TYPE:
        SetKey320Ipv6View0(V, l4Type_f, p_buffer->key, data);
        SetKey320Ipv6View0(V, l4Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L3_TYPE:
        SetKey320Ipv6View0(V, l3Type_f, p_buffer->key, data);
        SetKey320Ipv6View0(V, l3Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_ICMP_CODE:
    case CTC_FIELD_KEY_ICMP_TYPE:
        tmp_data = GetKey320Ipv6View0(V, l4Sport_f, p_buffer->key);
        tmp_mask = GetKey320Ipv6View0(V, l4Sport_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_ICMP_TYPE)
        {
            tmp_data &= (0x00ff);
            tmp_mask &= (0x00ff);
            tmp_data |= ((data << 8)&0xff00);
            tmp_mask |=((mask << 8)&0xff00);
        }
        else
        {
            tmp_data &= (0xff00);
            tmp_mask &= (0xff00);
            tmp_data |= (data & 0xff);
            tmp_mask |= (mask & 0xff);
        }
        data = tmp_data;
        mask = tmp_mask;
     case CTC_FIELD_KEY_L4_SRC_PORT:
        SetKey320Ipv6View0(V, l4Sport_f, p_buffer->key, data);
        SetKey320Ipv6View0(V, l4Sport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_TCP_FLAGS:
        SetKey320Ipv6View0(V, tcpFlag_f, p_buffer->key, data);
        SetKey320Ipv6View0(V, tcpFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_FRAG:
        SetKey320Ipv6View0(V, fragmentFlag_f, p_buffer->key, data);
        SetKey320Ipv6View0(V, fragmentFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_OPTIONS:
        SetKey320Ipv6View0(V, ipOption_f, p_buffer->key, data);
        SetKey320Ipv6View0(V, ipOption_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PROTOCOL:
        SetKey320Ipv6View0(V, ipProtocol_f, p_buffer->key, data);
        SetKey320Ipv6View0(V, ipProtocol_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_DSCP:
        SetKey320Ipv6View0(V, tos_f, p_buffer->key, data << 2);
        SetKey320Ipv6View0(V, tos_f, p_buffer->mask, mask << 2);
        break;
    case CTC_FIELD_KEY_IPV6_SA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        SetKey320Ipv6View0(A, sip_f, p_buffer->key, hw_ip6);
	  CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_mask);
        SetKey320Ipv6View0(A, sip_f, p_buffer->mask, hw_ip6);
        break;
    case CTC_FIELD_KEY_IPV6_DA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        SetKey320Ipv6View0(V, dip0_f, p_buffer->key, hw_ip6[0]);
        SetKey320Ipv6View0(A, dip1_f, p_buffer->key, &hw_ip6[1]);
	  CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_mask);
        SetKey320Ipv6View0(V, dip0_f, p_buffer->mask, hw_ip6[0]);
        SetKey320Ipv6View0(A, dip1_f, p_buffer->mask, &hw_ip6[1]);
        break;
    case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
    case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
    case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
    case CTC_FIELD_KEY_CVLAN_RANGE:
    case CTC_FIELD_KEY_SVLAN_RANGE:
        range_bmp = GetKey320Ipv6View0(V, l4Sport_f, p_buffer->key);
        CTC_ERROR_RETURN(_ctc_asw_acl_update_range_bmp(lchip, &range_bmp, data));
        SetKey320Ipv6View0(V, l4Sport_f, p_buffer->key, range_bmp & 0xfff);
        SetKey320Ipv6View0(V, l4Sport_f, p_buffer->mask, range_bmp & 0xfff);
        break;
    case CTC_FIELD_KEY_HASH_VALID:
        SetKey320Ipv6View0(V, keyType_f, p_buffer->key, 0x6);
        SetKey320Ipv6View0(V, keyType_f, p_buffer->mask, 0xf);
        SetKey320Ipv6View0(V, valid_f, p_buffer->mask, 0x01);
        SetKey320Ipv6View0(V, valid0_f, p_buffer->mask, 0x01);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}


STATIC int32
__ctc_asw_acl_add_macipv6udfkey640_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add)
{
    uint32 data = 0;
    uint32 mask = 0;
    uint32 udf[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    uint32 udf_mask[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    ctc_acl_udf_t* p_udf = NULL;
    ctc_acl_udf_t* p_udf_mask = NULL;
    sys_acl_buffer_t* p_buffer = NULL;
    hw_mac_addr_t hw_mac = {0};
    uint16 range_bmp = 0;
    ipv6_addr_t hw_ip6 = {0};
    uint16 tmp_data = 0;
    uint16 tmp_mask = 0;
    drv_acl_port_info_t port_drv = {0};

    p_buffer = &pe->buffer;

    if(is_add)
    {
        data = key_field->data;
        mask = key_field->mask;
    }

    switch(key_field->type)
    {
    case CTC_FIELD_KEY_PORT:
        CTC_ERROR_RETURN(_ctc_asw_acl_build_port_info(lchip, key_field, &port_drv));
        SetKey640Macipv6udfView0(V, sportBitmap_f, p_buffer->key, port_drv.gport);
        SetKey640Macipv6udfView0(V, sportBitmap_f, p_buffer->mask, port_drv.gport_mask);
        SetKey640Macipv6udfView0(V, portType_f, p_buffer->key, port_drv.gport_type);
        SetKey640Macipv6udfView0(V, portType_f, p_buffer->mask, port_drv.gport_type_mask);
        break;
    case CTC_FIELD_KEY_L4_TYPE:
        SetKey640Macipv6udfView0(V, l4Type_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, l4Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L3_TYPE:
        SetKey640Macipv6udfView0(V, l3Type_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, l3Type_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_ETHER_TYPE:
        SetKey640Macipv6udfView0(V, ethtype_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, ethtype_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_MAC_SA:
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_data));
        SetKey640Macipv6udfView0(A, sa_f, p_buffer->key, hw_mac);
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_mask));
        SetKey640Macipv6udfView0(A, sa_f, p_buffer->mask, hw_mac);
        break;
    case CTC_FIELD_KEY_MAC_DA:
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_data));
        SetKey640Macipv6udfView0(A, da_f, p_buffer->key, hw_mac);
        ACL_SET_HW_MAC(hw_mac, (uint8*)(key_field->ext_mask));
        SetKey640Macipv6udfView0(A, da_f, p_buffer->mask, hw_mac);
        break;
    case CTC_FIELD_KEY_STAG_VALID:
        SetKey640Macipv6udfView0(V, stagStatus_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, stagStatus_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_CTAG_VALID:
        SetKey640Macipv6udfView0(V, ctagStatus_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, ctagStatus_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_SVLAN_ID:
    case CTC_FIELD_KEY_STAG_COS:
    case CTC_FIELD_KEY_STAG_CFI:
        tmp_data = GetKey640Macipv6udfView0(V, stag_f, p_buffer->key);
        tmp_mask = GetKey640Macipv6udfView0(V, stag_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_SVLAN_ID)
        {
            tmp_data &= (~0xfff);
            tmp_mask &= (~0xfff);
            tmp_data |= (data & 0xfff);
            tmp_mask |= (mask & 0xfff);
        }
        else if (key_field->type == CTC_FIELD_KEY_STAG_COS)
        {
            tmp_data &= ~(0x7 << 13);
            tmp_mask &= ~(0x7 << 13);
            tmp_data |= ((data & 0x7) << 13);
            tmp_mask |= ((mask & 0x7) << 13);
        }
        else
        {

            tmp_data &= ~(0x1 << 12);
            tmp_mask &= ~(0x1 << 12);
            tmp_data |= ((data & 0x1) << 12);
            tmp_mask |= ((mask & 0x1) << 12);
        }
        SetKey640Macipv6udfView0(V, stag_f, p_buffer->key, tmp_data);
        SetKey640Macipv6udfView0(V, stag_f, p_buffer->mask, tmp_mask);
        break;
    case CTC_FIELD_KEY_CVLAN_ID:
    case CTC_FIELD_KEY_CTAG_COS:
    case CTC_FIELD_KEY_CTAG_CFI:
        tmp_data = GetKey640Macipv6udfView0(V, ctag_f, p_buffer->key);
        tmp_mask = GetKey640Macipv6udfView0(V, ctag_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_CVLAN_ID)
        {
            tmp_data &= (~0xfff);
            tmp_mask &= (~0xfff);
            tmp_data |= (data & 0xfff);
            tmp_mask |= (mask & 0xfff);
        }
        else if (key_field->type == CTC_FIELD_KEY_CTAG_COS)
        {
            tmp_data &= ~(0x7 << 13);
            tmp_mask &= ~(0x7 << 13);
            tmp_data |= ((data & 0x7) << 13);
            tmp_mask |= ((mask & 0x7) << 13);
        }
        else
        {

            tmp_data &= ~(0x1 << 12);
            tmp_mask &= ~(0x1 << 12);
            tmp_data |= ((data & 0x1) << 12);
            tmp_mask |= ((mask & 0x1) << 12);
        }
        SetKey640Macipv6udfView0(V, ctag_f, p_buffer->key, tmp_data);
        SetKey640Macipv6udfView0(V, ctag_f, p_buffer->mask, tmp_mask);
        break;

    case CTC_FIELD_KEY_ICMP_CODE:
    case CTC_FIELD_KEY_ICMP_TYPE:
        tmp_data = GetKey640Macipv6udfView0(V, l4Sport_f, p_buffer->key);
        tmp_mask = GetKey640Macipv6udfView0(V, l4Sport_f, p_buffer->mask);
        if(key_field->type == CTC_FIELD_KEY_ICMP_TYPE)
        {
            tmp_data &= (0x00ff);
            tmp_mask &= (0x00ff);
            tmp_data |= ((data << 8)&0xff00);
            tmp_mask |=((mask << 8)&0xff00);
        }
        else
        {
            tmp_data &= (0xff00);
            tmp_mask &= (0xff00);
            tmp_data |= (data & 0xff);
            tmp_mask |= (mask & 0xff);
        }
        data = tmp_data;
        mask = tmp_mask;
     case CTC_FIELD_KEY_L4_SRC_PORT:
        SetKey640Macipv6udfView0(V, l4Sport_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, l4Sport_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_L4_DST_PORT:
       SetKey640Macipv6udfView0(V, l4Dport_f, p_buffer->key, data);
       SetKey640Macipv6udfView0(V, l4Dport_f, p_buffer->mask, mask);
       break;
    case CTC_FIELD_KEY_TCP_FLAGS:
        SetKey640Macipv6udfView0(V, tcpFlag_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, tcpFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_FRAG:
        SetKey640Macipv6udfView0(V, fragmentFlag_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, fragmentFlag_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_OPTIONS:
        SetKey640Macipv6udfView0(V, ipOption_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, ipOption_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_PROTOCOL:
        SetKey640Macipv6udfView0(V, ipProtocol_f, p_buffer->key, data);
        SetKey640Macipv6udfView0(V, ipProtocol_f, p_buffer->mask, mask);
        break;
    case CTC_FIELD_KEY_IP_DSCP:
        SetKey640Macipv6udfView0(V, tos_f, p_buffer->key, data << 2);
        SetKey640Macipv6udfView0(V, tos_f, p_buffer->mask, mask << 2);
        break;
    case CTC_FIELD_KEY_IPV6_SA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        data = hw_ip6[0]&0x1FFF;
        SetKey640Macipv6udfView0(V, sip0_f, p_buffer->key, data);
        hw_ip6[0] = hw_ip6[0]>>13 | ((hw_ip6[1]<<19)&0xFFF80000);
        hw_ip6[1] = hw_ip6[1]>>13 | ((hw_ip6[2]<<19)&0xFFF80000);
        hw_ip6[2] = hw_ip6[2]>>13 | ((hw_ip6[3]<<19)&0xFFF80000);
        hw_ip6[3] = hw_ip6[3]>>13;
        SetKey640Macipv6udfView0(A, sip1_f, p_buffer->key, hw_ip6);
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_mask);
        data = hw_ip6[0]&0x1FFF;
        SetKey640Macipv6udfView0(V, sip0_f, p_buffer->mask, data);
        hw_ip6[0] = hw_ip6[0]>>13 | ((hw_ip6[1]<<19)&0xFFF80000);
        hw_ip6[1] = hw_ip6[1]>>13 | ((hw_ip6[2]<<19)&0xFFF80000);
        hw_ip6[2] = hw_ip6[2]>>13 | ((hw_ip6[3]<<19)&0xFFF80000);
        hw_ip6[3] = hw_ip6[3]>>13;
        SetKey640Macipv6udfView0(A, sip1_f, p_buffer->mask, hw_ip6);
        break;
    case CTC_FIELD_KEY_IPV6_DA:
        CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_data);
        SetKey640Macipv6udfView0(A, dip0_f, p_buffer->key, hw_ip6);
        SetKey640Macipv6udfView0(A, dip1_f, p_buffer->key, (uint8*)((uint8*)hw_ip6+6));
	  CTC_ASW_REVERT_IP6(hw_ip6, (uint32*)key_field->ext_mask);
        SetKey640Macipv6udfView0(A, dip0_f, p_buffer->mask, hw_ip6);
        SetKey640Macipv6udfView0(A, dip1_f, p_buffer->mask, (uint8*)((uint8*)hw_ip6+6));
        break;
    case CTC_FIELD_KEY_IP_PKT_LEN_RANGE:
    case CTC_FIELD_KEY_L4_SRC_PORT_RANGE:
    case CTC_FIELD_KEY_L4_DST_PORT_RANGE:
    case CTC_FIELD_KEY_CVLAN_RANGE:
    case CTC_FIELD_KEY_SVLAN_RANGE:
        range_bmp = GetKey640Macipv6udfView0(V, rangeBitmap_f, p_buffer->key);
        range_bmp = (range_bmp << 8);
        range_bmp |= GetKey640Macipv6udfView0(V, rangeBitmap0_f, p_buffer->key);
        CTC_ERROR_RETURN(_ctc_asw_acl_update_range_bmp(lchip, &range_bmp, data));
        SetKey640Macipv6udfView0(V, rangeBitmap_f, p_buffer->key, (range_bmp >> 8)&0xF);
        SetKey640Macipv6udfView0(V, rangeBitmap0_f, p_buffer->key, (range_bmp & 0xFF));
        SetKey640Macipv6udfView0(V, rangeBitmap_f, p_buffer->mask, 0xF);
        SetKey640Macipv6udfView0(V, rangeBitmap0_f, p_buffer->mask, 0xFF);
        break;
    case CTC_FIELD_KEY_HASH_VALID:
        SetKey640Macipv6udfView0(V, keyType_f, p_buffer->key, 0x7);
        SetKey640Macipv6udfView0(V, keyType_f, p_buffer->mask, 0x0f);
        SetKey640Macipv6udfView0(V, valid_f, p_buffer->mask, 0x01);
        SetKey640Macipv6udfView0(V, valid0_f, p_buffer->mask, 0x01);
        SetKey640Macipv6udfView0(V, valid1_f, p_buffer->mask, 0x01);
        SetKey640Macipv6udfView0(V, valid2_f, p_buffer->mask, 0x01);
        break;
    case CTC_FIELD_KEY_UDF:
        p_udf = (ctc_acl_udf_t*)key_field->ext_data;
        p_udf_mask = (ctc_acl_udf_t*)key_field->ext_mask;
        CTC_ASW_SET_HW_UDF(udf, p_udf->udf);
        CTC_ASW_SET_HW_UDF(udf_mask, p_udf_mask->udf);
        SetKey640Macipv6udfView0(V, udfIndex_f, p_buffer->key, p_udf->udf_id);
        SetKey640Macipv6udfView0(V, udfIndex_f, p_buffer->mask, 7);
        SetKey640Macipv6udfView0(V, udf0_f, p_buffer->key, udf[0]);
        SetKey640Macipv6udfView0(V, udf0_f, p_buffer->mask, udf_mask[0]);
        SetKey640Macipv6udfView0(V, udf1_f, p_buffer->key, udf[1]);
        SetKey640Macipv6udfView0(V, udf1_f, p_buffer->mask, udf_mask[1]);
        SetKey640Macipv6udfView0(V, udf2_f, p_buffer->key, udf[2]);
        SetKey640Macipv6udfView0(V, udf2_f, p_buffer->mask, udf_mask[2]);
        SetKey640Macipv6udfView0(V, udf3_f, p_buffer->key, udf[3]);
        SetKey640Macipv6udfView0(V, udf3_f, p_buffer->mask, udf_mask[3]);
        SetKey640Macipv6udfView0(V, udfValid_f, p_buffer->key, 0xf);
        SetKey640Macipv6udfView0(V, udfValid_f, p_buffer->mask, 0xf);
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }
    return CTC_E_NONE;
}



STATIC int32
_ctc_asw_acl_register_build_key_fn()
{

    g_acl_build_key_func_cb[CTC_ACL_KEY_MAC]        = __ctc_asw_acl_add_mackey160_field;
    g_acl_build_key_func_cb[CTC_ACL_KEY_MAC_EXT]    = __ctc_asw_acl_add_macudfkey160_field;
    g_acl_build_key_func_cb[CTC_ACL_KEY_IPV4]       = __ctc_asw_acl_add_ipkey160_field;
    g_acl_build_key_func_cb[CTC_ACL_KEY_MAC_IPV4]   = __ctc_asw_acl_add_macipudfkey320_field;
    g_acl_build_key_func_cb[CTC_ACL_KEY_IPV4_EXT]   = __ctc_asw_acl_add_ipudfkey320_field;
    g_acl_build_key_func_cb[CTC_ACL_KEY_MAC_IPV6]   = __ctc_asw_acl_add_macipv6key640_field;
    g_acl_build_key_func_cb[CTC_ACL_KEY_IPV6]       = __ctc_asw_acl_add_ipv6key320_field;
    g_acl_build_key_func_cb[CTC_ACL_KEY_IPV6_EXT]   = __ctc_asw_acl_add_macipv6udfkey640_field;
    g_acl_build_key_func_cb[CTC_ACL_KEY_UDF]        = __ctc_asw_acl_add_ethudfkey160_field;

    return CTC_E_NONE;
}

STATIC int32
_ctc_asw_acl_init_global_cfg(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 key_mode = 1;
    uint32 key_ctrl = 0;
    cmd = DRV_IOW(AclGlobalKeyMode_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd , &key_mode));

    SetAclGlobalKeyCtrl(V, ipv6Sa32Sel_f, &key_ctrl, 1);
    SetAclGlobalKeyCtrl(V, ipv6Da32Sel_f, &key_ctrl, 1);
    SetAclGlobalKeyCtrl(V, vidMode_f, &key_ctrl, 0);
    SetAclGlobalKeyCtrl(V, dscpMode_f, &key_ctrl, 1);
    cmd = DRV_IOW(AclGlobalKeyCtrl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd , &key_ctrl));
    return CTC_E_NONE;
}

int32
_ctc_asw_acl_check_action_field(uint8 lchip, ctc_acl_field_action_t* p_field_list, uint32* p_field_cnt)
{
    uint32  field_id      = 0;
    ctc_acl_field_action_t* p_field = NULL;
    uint32 field_cnt = *p_field_cnt;
    uint8 stats_en = 0;
    uint8 policer_en = 0;

    for (field_id=0; field_id<field_cnt; field_id++)
    {
        p_field = p_field_list + field_id;
        CTC_PTR_VALID_CHECK(p_field);
        if(CTC_ACL_FIELD_ACTION_STATS == p_field->type)
        {
            stats_en = 1;
        }

        if (CTC_ACL_FIELD_ACTION_MICRO_FLOW_POLICER == p_field->type)
        {
            policer_en = 1;
        }
    }
    
    if(stats_en && policer_en)
    {
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

#define _________api_function__________
int32
ctc_asw_acl_init(uint8 lchip, ctc_acl_global_cfg_t* acl_global_cfg)
{
    LoopbackProfile_m loopback_profile;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    CTC_API_LOCK(lchip);
    _ctc_asw_acl_register_build_key_fn();

    g_acl_key_size[CTC_ACL_KEY_MAC] = 1;
    g_acl_key_tbl[CTC_ACL_KEY_MAC] = Key160MacView0_t;
    g_acl_key_size[CTC_ACL_KEY_MAC_EXT] = 1;
    g_acl_key_tbl[CTC_ACL_KEY_MAC_EXT] = Key160MacudfView0_t;
    g_acl_key_size[CTC_ACL_KEY_IPV4] = 1;
    g_acl_key_tbl[CTC_ACL_KEY_IPV4] = Key160IpView0_t;
    g_acl_key_size[CTC_ACL_KEY_IPV6] = 2;
    g_acl_key_tbl[CTC_ACL_KEY_IPV6] = Key320Ipv6View0_t;
    g_acl_key_size[CTC_ACL_KEY_IPV4_EXT] = 2;
    g_acl_key_tbl[CTC_ACL_KEY_IPV4_EXT] = Key320IpudfView0_t;
    g_acl_key_size[CTC_ACL_KEY_MAC_IPV4] = 2;
    g_acl_key_tbl[CTC_ACL_KEY_MAC_IPV4] = Key320MacipudfView0_t;
    g_acl_key_size[CTC_ACL_KEY_IPV6_EXT] = 4;
    g_acl_key_tbl[CTC_ACL_KEY_IPV6_EXT] = Key640Macipv6udfView0_t;
    g_acl_key_size[CTC_ACL_KEY_MAC_IPV6] = 2;
    g_acl_key_tbl[CTC_ACL_KEY_MAC_IPV6] = Key640Macipv6View0_t;
    g_acl_key_size[CTC_ACL_KEY_UDF] = 1;
    g_acl_key_tbl[CTC_ACL_KEY_UDF] = Key160EthudfView0_t;

    ret = _ctc_asw_acl_init_global_cfg(lchip);
    /*profile index 0 for swap mac and fwd*/
    cmd = DRV_IOR(LoopbackProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, cmd, &loopback_profile));
    SetLoopbackProfile(V,saUnicastAct_f, &loopback_profile, 1);
    SetLoopbackProfile(V,loopbackFwdMode_f, &loopback_profile, 1);
    cmd = DRV_IOW(LoopbackProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, cmd , &loopback_profile));
    cmd = DRV_IOR(LoopbackProfile_t, DRV_ENTRY_FLAG);
    /*profile index 1 for swap mac and nofwd*/
    CTC_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 1, cmd, &loopback_profile));
    SetLoopbackProfile(V,saUnicastAct_f, &loopback_profile, 1);
    SetLoopbackProfile(V,loopbackFwdMode_f, &loopback_profile, 0);
    cmd = DRV_IOW(LoopbackProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 1, cmd , &loopback_profile));
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_acl_deinit(uint8 lchip)
{
    return CTC_E_NONE;
}

int32
_ctc_asw_acl_add_entry(uint8 lchip, uint32 group_id, ctc_acl_entry_t* acl_entry)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 key_tbl = 0;
    sys_acl_entry_t pe;
    mask_tbl_entry_t tcam_key;
    ctc_field_key_t  key_field;

    tcam_key.data_entry = pe.buffer.key;
    tcam_key.mask_entry = pe.buffer.mask;
    sal_memset(&pe.buffer, 0 ,sizeof(sys_acl_buffer_t));
    sal_memset(&key_field, 0 ,sizeof(ctc_field_key_t));

    key_tbl = g_acl_key_tbl[acl_entry->key_type];
    cmd = DRV_IOR(key_tbl, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_MASK_IOCTL(lchip, acl_entry->entry_id, cmd, &tcam_key),ret,error_pro);

    CTC_ERROR_GOTO(_ctc_asw_acl_check_key_index(lchip, acl_entry, tcam_key.data_entry),ret,error_pro);
    sal_memset(pe.buffer.mask, 0, sizeof(ds_t));
    key_field.type = CTC_FIELD_KEY_HASH_VALID;
    CTC_ERROR_GOTO(g_acl_build_key_func_cb[acl_entry->key_type](lchip, &key_field, &pe, 1),ret,error_pro);

    cmd = DRV_IOW(key_tbl, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_MASK_IOCTL(lchip, acl_entry->entry_id, cmd, &tcam_key),ret,error_pro);
error_pro:
    return ret;
}

int32
ctc_asw_acl_add_entry(uint8 lchip, uint32 group_id, ctc_acl_entry_t* acl_entry)
{
    int32 ret = CTC_E_NONE;
    CTC_PTR_VALID_CHECK(acl_entry);
    ACL_ENTRY_ID_CHECK(acl_entry->entry_id);
    CTC_MAX_VALUE_CHECK(acl_entry->key_type, CTC_ACL_KEY_NUM-1);

    if((0 == g_acl_key_size[acl_entry->key_type]) || acl_entry->entry_id % g_acl_key_size[acl_entry->key_type])
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_API_LOCK(lchip);
    ret = _ctc_asw_acl_add_entry(lchip, group_id, acl_entry);
    CTC_API_UNLOCK(lchip);
    return ret;

}

int32
ctc_asw_acl_remove_entry(uint8 lchip, uint32 entry_id)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint8 key_type = 0;
    AclBaseAction_m action;
    AclQosAction_m qos_action;

    sal_memset(&action, 0, sizeof(AclBaseAction_m));
    sal_memset(&qos_action, 0, sizeof(AclQosAction_m));
    
    ACL_ENTRY_ID_CHECK(entry_id);
    CTC_API_LOCK(lchip);
    CTC_ERROR_RETURN_UNLOCK(_ctc_asw_acl_get_key_type(lchip, entry_id, &key_type, 0));

    cmd = DRV_IOD(g_acl_key_tbl[key_type], DRV_ENTRY_FLAG);
    ret = DRV_MASK_IOCTL(lchip, entry_id, cmd, &cmd);

    cmd = DRV_IOW(AclBaseAction_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, entry_id, cmd, &action);

    cmd = DRV_IOW(AclQosAction_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, entry_id, cmd, &qos_action);

    CTC_API_UNLOCK(lchip);
    return ret;
}


int32
_ctc_asw_acl_add_key_field_list(uint8 lchip, uint32 entry_id, ctc_field_key_t* p_field_list, uint32* p_field_cnt)
{
    uint32  field_id      = 0;
    uint32 tmp_data = 0;
    uint32 tmp_mask = 0;
    uint32 cmd = 0;
    uint32 field_cnt = 0;
    sys_acl_entry_t pe;
    mask_tbl_entry_t tcam_key;
    ctc_field_key_t* key_field = NULL;
    ds_t  ext_mask_temp = {0};

    sal_memset(&pe.buffer, 0 ,sizeof(sys_acl_buffer_t));
    tcam_key.data_entry = pe.buffer.key;
    tcam_key.mask_entry = pe.buffer.mask;
    field_cnt = *p_field_cnt;
    *p_field_cnt = 0;

    CTC_ERROR_RETURN(_ctc_asw_acl_get_key_type(lchip, entry_id, &pe.key_type, 0));

    cmd = DRV_IOR(g_acl_key_tbl[pe.key_type], DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, entry_id, cmd, &tcam_key));

    CTC_ERROR_RETURN(_ctc_asw_acl_check_key_field(pe.key_type, p_field_list, field_cnt));

    for (field_id=0; field_id<field_cnt; field_id+=1)
    {
        key_field = p_field_list + field_id;

        /*check*/
        if (NULL == key_field)
        {
            return CTC_E_NOT_EXIST;
        }

        if(key_field->ext_mask == NULL)
        {
            sal_memset(ext_mask_temp, 0xFF, sizeof(ds_t));
            key_field->ext_mask = ext_mask_temp;
        }

        if(key_field->type == CTC_FIELD_KEY_L3_TYPE)
        {
            _ctc_asw_acl_map_l3_type(key_field->data, &tmp_data);
            key_field->data = tmp_data;
        }
        else if(key_field->type == CTC_FIELD_KEY_L4_TYPE)
        {
            _ctc_asw_acl_map_l4_type(key_field->data, &tmp_data);
            key_field->data = tmp_data;
        }
        else if (key_field->type == CTC_FIELD_KEY_IP_FRAG)
        {
            _ctc_asw_acl_map_ip_frag(key_field->data, &tmp_data, &tmp_mask);
            key_field->data = tmp_data;
            key_field->mask = tmp_mask;
        }
        CTC_ERROR_RETURN(g_acl_build_key_func_cb[pe.key_type](lchip, key_field, &pe, 1));
        (*p_field_cnt)++;
    }

    cmd = DRV_IOW(g_acl_key_tbl[pe.key_type], DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_MASK_IOCTL(lchip, entry_id, cmd, &tcam_key));

    return CTC_E_NONE;
}

int32
ctc_asw_acl_add_key_field_list(uint8 lchip, uint32 entry_id, ctc_field_key_t* p_field_list, uint32* p_field_cnt)
{
    int32 ret = CTC_E_NONE;
    ACL_ENTRY_ID_CHECK(entry_id);
    CTC_PTR_VALID_CHECK(p_field_list);
    CTC_PTR_VALID_CHECK(p_field_cnt);
    CTC_API_LOCK(lchip);
    ret = _ctc_asw_acl_add_key_field_list(lchip, entry_id, p_field_list, p_field_cnt);
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_acl_remove_key_field_list(uint32 entry_id, ctc_field_key_t* p_field_list, uint32* p_field_cnt)
{
    return CTC_E_NONE;
}

int32
ctc_asw_acl_add_action_field_list(uint8 lchip, uint32 entry_id, ctc_acl_field_action_t* p_field_list, uint32* p_field_cnt)
{
    int32 ret = CTC_E_NONE;
    CTC_PTR_VALID_CHECK(p_field_list);
    CTC_PTR_VALID_CHECK(p_field_cnt);
    ACL_ENTRY_ID_CHECK(entry_id);
    CTC_API_LOCK(lchip);

    ret = _ctc_asw_acl_check_action_field(lchip, p_field_list, p_field_cnt);
    ret = ret?ret:_ctc_asw_acl_build_action_field_list(lchip, entry_id, p_field_list, p_field_cnt, 1);

    CTC_API_UNLOCK(lchip);
    return ret;
}


int32
ctc_asw_acl_remove_action_field_list(uint8 lchip, uint32 entry_id, ctc_acl_field_action_t* p_field_list, uint32* p_field_cnt)
{
    int32 ret = CTC_E_NONE;
    CTC_PTR_VALID_CHECK(p_field_list);
    ACL_ENTRY_ID_CHECK(entry_id);
    CTC_API_LOCK(lchip);

    ret = _ctc_asw_acl_build_action_field_list(lchip, entry_id, p_field_list, p_field_cnt, 0);

    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
_ctc_asw_acl_install_entry(uint8 lchip, uint32 entry_id)
{
    int32 ret = CTC_E_NONE;
    AclBaseAction_m action;
    uint32 cmd = 0;
    ACL_ENTRY_ID_CHECK(entry_id);

    sal_memset(&action, 0, sizeof(action));

    ret = _ctc_asw_acl_add_remove_valid(lchip, entry_id, 1);
    cmd = DRV_IOR(AclBaseAction_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, entry_id, cmd, &action);
    SetAclBaseAction(V, expEgressPortBitmap_f, &action, 0x1fffffff);
    cmd = DRV_IOW(AclBaseAction_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, entry_id, cmd, &action);

    return  ret;
}

int32
ctc_asw_acl_install_entry(uint8 lchip, uint32 entry_id)
{
    int32 ret = CTC_E_NONE;
    CTC_API_LOCK(lchip);
    ret = _ctc_asw_acl_install_entry(lchip, entry_id);
    CTC_API_UNLOCK(lchip);
    return  ret;
}


int32
ctc_asw_acl_uninstall_entry(uint8 lchip, uint32 entry_id)
{
    int32 ret = CTC_E_NONE;
    ACL_ENTRY_ID_CHECK(entry_id);

    CTC_API_LOCK(lchip);
    ret = _ctc_asw_acl_add_remove_valid(lchip, entry_id, 0);
    CTC_API_UNLOCK(lchip);

    return  ret;
}


/********************** range info *******************************/

int32
ctc_asw_acl_add_range_info(uint8 lchip, ctc_acl_range_t* range_info, uint8 index)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    AclRangeCheck_m ds_range;

    CTC_PTR_VALID_CHECK(range_info);

    if(index >= CTC_ASW_ACL_RANGE_NUM || range_info->type >= CTC_ACL_RANGE_TYPE_NUM)
    {
        return CTC_E_INVALID_PARAM;
    }
    if(range_info->min > range_info->max)
    {
        return CTC_E_INVALID_PARAM;
    }
    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(AclRangeCheck_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, index, cmd, &ds_range);

    if(GetAclRangeCheck(V, valid_f, &ds_range))
    {
        if(GetAclRangeCheck(V, optype_f, &ds_range) != range_info->type)
        {
            CTC_API_UNLOCK(lchip);
            return CTC_E_EXIST;
        }
    }

    SetAclRangeCheck(V, optype_f, &ds_range, range_info->type);
    SetAclRangeCheck(V, maxVal_f, &ds_range, range_info->max);
    SetAclRangeCheck(V, minVal_f, &ds_range, range_info->min);
    SetAclRangeCheck(V, valid_f, &ds_range, 1);

    cmd = DRV_IOW(AclRangeCheck_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, index, cmd, &ds_range);

    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_acl_remove_range_info(uint8 lchip,        uint8 index)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    AclRangeCheck_m ds_range;
    CTC_MAX_VALUE_CHECK(index, CTC_ASW_ACL_RANGE_NUM - 1);
    CTC_API_LOCK(lchip);
    sal_memset(&ds_range, 0, sizeof(AclRangeCheck_m));
    cmd = DRV_IOW(AclRangeCheck_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, index, cmd, &ds_range);

    CTC_API_UNLOCK(lchip);
    return ret;
}

/************************* udf *******************************/
int32
ctc_asw_acl_add_udf_entry(uint8 lchip, ctc_acl_classify_udf_t* p_udf_entry)
{
    int32  ret = CTC_E_NONE;
    UdfOffset_m udf_rst;
    UdfCam_m udf_cam;
    UdfCam_m udf_cam_mask;
    uint32 cmd = 0;
    uint8 idx = 0;
    uint8 offset_drv[CTC_ASW_ACL_UDF_FIELD_NUM] = {0};
    uint8  udf_type_none[CTC_ASW_ACL_UDF_FIELD_NUM] = {CTC_ACL_UDF_TYPE_NONE};
    mask_tbl_entry_t udf_entry;

    CTC_PTR_VALID_CHECK(p_udf_entry);
    ACL_UDF_ID_CHECK(p_udf_entry->udf_id);

    sal_memset(&udf_cam, 0, sizeof(UdfCam_m));
    sal_memset(&udf_cam_mask, 0, sizeof(UdfCam_m));
    sal_memset(&udf_rst, 0, sizeof(UdfOffset_m));
    udf_entry.data_entry = (uint32 *)&udf_cam;
    udf_entry.mask_entry = (uint32 *)&udf_cam_mask;

    CTC_MAX_VALUE_CHECK(p_udf_entry->offset_num, 4);
    for(idx=0; idx < CTC_ASW_ACL_UDF_FIELD_NUM; idx++)
    {
        CTC_MAX_VALUE_CHECK(p_udf_entry->offset_type_array[idx], CTC_ACL_UDF_OFFSET_L4);
        offset_drv[idx] = p_udf_entry->offset[idx];
        
        if(p_udf_entry->offset_type_array[idx] == CTC_ACL_UDF_OFFSET_L2)
        {
        /* for spec bug */
        /*  drv offset: |      0      |  1  |  2  | .... |    30   |   31    |
         *  ext bytes : | 126-127,0-1 | 2-5 | 6-9 |      | 118-121 | 122-125 |   */

            if(p_udf_entry->offset[idx] < 2)
            {
                return CTC_E_INVALID_PARAM;
            }
            offset_drv[idx] = p_udf_entry->offset[idx] + 2;
        }
        if(offset_drv[idx] % 4)
        {
            return CTC_E_INVALID_PARAM;
        }
        CTC_MAX_VALUE_CHECK(offset_drv[idx]>>2, 0x1f);
    }

    CTC_API_LOCK(lchip);

    cmd = DRV_IOR(UdfCam_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_UNLOCK(DRV_MASK_IOCTL(lchip, p_udf_entry->udf_id, cmd, &udf_entry));
    if(GetUdfCam(V, valid_f, &udf_cam))
    {
        CTC_API_UNLOCK(lchip);
        return CTC_E_EXIST;
    }
    sal_memset(&udf_cam_mask, 0, sizeof(UdfCam_m));
    SetUdfOffset(V, udf0Offset_f, &udf_rst, offset_drv[0]>>2);
    SetUdfOffset(V, udf1Offset_f, &udf_rst, offset_drv[1]>>2);
    SetUdfOffset(V, udf2Offset_f, &udf_rst, offset_drv[2]>>2);
    SetUdfOffset(V, udf3Offset_f, &udf_rst, offset_drv[3]>>2);

    if (sal_memcmp(p_udf_entry->offset_type_array, udf_type_none, sizeof(p_udf_entry->offset_type_array)))
    {
        SetUdfOffset(V, udf0BaseType_f, &udf_rst, p_udf_entry->offset_type_array[0]);
        SetUdfOffset(V, udf1BaseType_f, &udf_rst, p_udf_entry->offset_type_array[1]);
        SetUdfOffset(V, udf2BaseType_f, &udf_rst, p_udf_entry->offset_type_array[2]);
        SetUdfOffset(V, udf3BaseType_f, &udf_rst, p_udf_entry->offset_type_array[3]);
    }
    else
    {
        CTC_API_UNLOCK(lchip);
        return CTC_E_INVALID_PARAM;
    }

    cmd = DRV_IOW(UdfOffset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, p_udf_entry->udf_id, cmd, &udf_rst));
    cmd = DRV_IOW(UdfCam_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_UNLOCK(DRV_MASK_IOCTL(lchip, p_udf_entry->udf_id, cmd, &udf_entry));

    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_acl_remove_udf_entry(uint8 lchip, ctc_acl_classify_udf_t* udf_entry)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    UdfOffset_m udf_offset;

    CTC_PTR_VALID_CHECK(udf_entry);
    ACL_UDF_ID_CHECK(udf_entry->udf_id);
    CTC_API_LOCK(lchip);

    cmd = DRV_IOD(UdfCam_t, DRV_ENTRY_FLAG);
    ret = DRV_MASK_IOCTL(lchip, udf_entry->udf_id, cmd, &cmd);

    sal_memset(&udf_offset, 0, sizeof(UdfOffset_m));
    cmd = DRV_IOW(UdfOffset_t, DRV_ENTRY_FLAG);
    ret = ret?ret:DRV_IOCTL(lchip, udf_entry->udf_id, cmd, &udf_offset);

    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_acl_add_udf_entry_key_field(uint8 lchip,  uint32 udf_id, ctc_field_key_t* key_field)
{
    uint32 cmd = 0;
    mask_tbl_entry_t udf_entry;
    UdfCam_m udf_cam;
    UdfCam_m udf_mask;

    ACL_UDF_ID_CHECK(udf_id);
    CTC_PTR_VALID_CHECK(key_field);

    udf_entry.data_entry = (uint32 *)&udf_cam;
    udf_entry.mask_entry = (uint32 *)&udf_mask;

    sal_memset(&udf_cam, 0, sizeof(udf_cam));
    sal_memset(&udf_mask, 0, sizeof(udf_mask));

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(UdfCam_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_UNLOCK(DRV_MASK_IOCTL(lchip, udf_id, cmd, &udf_entry));

    if(GetUdfCam(V, valid_f, &udf_cam))
    {
        CTC_API_UNLOCK(lchip);
        return CTC_E_EXIST;
    }

    CTC_ERROR_RETURN_UNLOCK(_ctc_asw_acl_check_udf_entry_key_field(lchip, key_field));
    CTC_ERROR_RETURN_UNLOCK(_ctc_asw_acl_add_udf_entry_key_field(lchip, &udf_entry, key_field, 1));
    cmd = DRV_IOW(UdfCam_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_UNLOCK(DRV_MASK_IOCTL(lchip, udf_id, cmd, &udf_entry));
    CTC_API_UNLOCK(lchip);

    return CTC_E_NONE;
}
